为何而写

  以前没怎么写过技术类的文章,对于技术很多时候是现用现学,这样通常能解决遇到过的绝大多数问题,但也带来了一个弊端,那就是仅停留于解决问题的层面,而忽略了对技术背后的设计思想和设计理念进行深入的研究。虽然技术的发展日新月异,但那些终归只是由设计思想演绎出来的玩物,如果只是不断的去学习演绎出来的东西,而忽略了对思想的研究,就终究会陷入舍本逐末的恶性循环。

  技术的提高离不开实践,实践有助于深化对技术的理解,但如果只实践而不加以总结的话也容易陷入只见树木不见森林的迷途。如果说实践是战术上的肉搏,那总结就是战略上的提炼,高屋建瓴,将实践中的精髓抽取出来,以达到去繁入简、返璞归真的境界。

  

  鉴于此,也就打算把学习、实践过的技术进行再次的学习、总结,并以博文的形式记录下来,这样一方面有助于理清思路,建立知识体系,另一方面更有助于深入对技术的理解和掌握,这也是我打算开始写技术文章的初衷。

  

redux是什么

  redux是一个库,用于管理状态,也可以说是一个容器,这个容器里容纳了各种需要的状态信息,并对外提供了一些方法来管理这些状态。目前redux更多的实践是和react结合,管理react的视图状态,但它也可以独立当作发布、订阅系统来使用。总之这些只是概念层面上的东西,实践完之后再来看概念就会容易理解,否则概念永远是模糊的。

redux的设计哲学

redux有三大设计哲学:

1、单一数据源。

顾名思义就是所有的状态信息都存储在同一个容器里。

2、状态是只读的。

redux是用来管理状态的,竟然能管理,那就包含了对状态的增、删、改操作。这里的只读是指新状态不会破坏原来的旧状态,也就是说新状态的产生过程是:1、先从旧状态进行深拷贝得到一个复本。2、对复本进行操作得到新状态。

3、使用纯函数来更新状态。

纯函数是指输入相同的参数时,总能得到相同的输出结果,并且不会修改输入的参数。

这三大设计哲学主要是为了简化对状态的管理,让状态可预测、可追踪,从而易于维护代码,也更易于排查bug。

redux的工作流

redux的工作流如下图所示:

https://slides.com/jenyaterpil/redux-from-twitter-hype-to-production#/9

redux的几个核心要素

store

redux是管理状态的,所有的状态都存储在“store”里,所以store是一个数据中心,也是最核心的要素。同时store对外暴露了一些api用于管理store里的数据,这些api包括getState、dispatch、subscribe、replaceReducer。store是由createStore函数创建的,如:

const store = createStore(reducer, preloadedState, enhancer)

createStore的实现原理如下:

const createStore = reducer => {
let state;
// listeners用来存储所有的监听函数
let listeners = []; const getState = () => state; const dispatch = action => {
state = reducer(state, action);
// 每一次状态更新后,都需要调用listeners数组中的每一个监听函数
listeners.forEach(listener => listener());
} const subscribe = listener => {
// subscribe可能会被调用多交,每一次调用时,都将相关的监听函数存入listeners数组中
listeners.push(listener);
// 返回一个函数,进行取消订阅
return () => {
listeners = listeners.filter(item => item !== listener);
}
} return { getState, dispatch, subscribe };
}

dispatch

dispatch用来派发一个action,所有对state的更新以及获取数据都是通过派发一个action来完成的。如:

let action1 = {
type: 'READ_BOOK',
data: {
book: 'book1'
}
}; store.dispatch(action1);

getState

getState用于获取store里的状态数据,即state。如:

let state = store.getState();

subscribe

subscribe用于订阅store里的数据状态,当store里state数据变更时,通知订阅方。如:

const render = () => {
...
} store.subscribe(render);

replaceReducer

这个一般开发用不到。

action

action是指一个操作动作,当需要操作store里的数据时,就需要分发一个action来通知store。每个action描述了一个操作,它是一个object的数据结构,有一个必填属性“type”,值是字符串常量,用于标识动作,可以理解为动作的ID,另外action对象里还可以携带其他数据信息,这要根据action所要完成的操作来定。

reducer

reducer是用来响应action来处理状态的,它会对每个分发的action进行操作,根据传过来的action和store里已有的sate值进行一些运算,然后返回新的state。

actionCreator

actionCreator是一个类似于工厂模式的生产工具,用于生产action。如:

const learnReduxActionFactory = book => {
type: 'READ_REDUX_BOOK',
book
}

combineReducers

combineReducers是Redux提供的一个工具函数,可以把多个拆分的reducer合并成一完整的reducer。

例如在页面状态中存储三种数据状态,分别为data1、data2和data3, 它们是相互独立的。如:

state = {
data1: {
...
},
data2: {
...
},
data3: {
...
}
};

同样我们把处理这三种数据状态的reducer函数也拆分成三个小的reducer,分别为reducer1、reducer2和reducer3。如下:

const reducer1 = (previousState= {}, action) => {
// 根据action和state.data1计算产生新的state.data1
return state.data1;
};
const reducer2 = (previousState= {}, action) => {
// 根据action和state.data2计算产生新的state.data2
return state.data2;
}
const reducer3 = (previousState= {}, action) => {
// 根据action和state.data3计算产生新的state.data3
return state.data3;
}

最后利用combineReducer将这三个子reducer函数合并成一个完整的reducer并返回。如下:

const { combineReducers } = Redux;
const finalReducer = combineReducers({
data1: reducer1,
data2: reducer2,
data3: reducer3
});

在ES6开发环境下,常用的做法是令子reducer函数名称和数据状态的命名保持一致,即将reducer1、reducer2、reducer3分别命名为data1、data2、data3。即:

const finalReducer = combineReducers({
data1: data1,
data2: data2,
data3: data3
});

也可以简写为:

const finalReducer = combineReducers({data1, data2, data3});

日常开发中,通常会将大的reducer拆分成多个小的reducer进行单独维护,这样的分治能提高维护效率。

redux中间件

redux中间件提供的是位于action被派发之后,到达reducer之前的扩展点,因此可以利用redux中间件来完成日志记录、调用异步接口或者路由等。redux中间件的作用主要有两个:

1、截获action

2、发出action

redux中间件异步请求的工作流如下图所示:

https://slides.com/jenyaterpil/redux-from-twitter-hype-to-production#/23

小结

redux既可以作为发布订阅系统独立使用,也可以和react结合来管理react组件的状态。目前最常见的使用场景是与react结合,让react组件间通信更加容易。另外通过使用丰富的redux中间件,能扩展系统的特性。

玩转redux--从会用到庖丁解牛的更多相关文章

  1. angular开发者吐槽react+redux的复杂:“一个demo证明你的开发效率低下”

    曾经看到一篇文章,写的是jquery开发者吐槽angular的复杂.作为一个angular开发者,我来吐槽一下react+redux的复杂. 例子 为了让大家看得舒服,我用最简单的一个demo来展示r ...

  2. redux+flux(一:入门篇)

    React是facebook推出的js框架,React 本身只涉及UI层,如果搭建大型应用,必须搭配一个前端框架.也就是说,你至少要学两样东西,才能基本满足需要:React + 前端框架. Faceb ...

  3. 基于react+react-router+redux+socket.io+koa开发一个聊天室

    最近练手开发了一个项目,是一个聊天室应用.项目虽不大,但是使用到了react, react-router, redux, socket.io,后端开发使用了koa,算是一个比较综合性的案例,很多概念和 ...

  4. 翻译:使用 Redux 和 ngrx 创建更佳的 Angular 2

    翻译:使用 Redux 和 ngrx 创建更佳的 Angular 2 原文地址:http://onehungrymind.com/build-better-angular-2-application- ...

  5. React+Redux实现追书神器网页版

    引言 由于现在做的react-native项目没有使用到redux等框架,写了一段时间想深入学习react,有个想法想做个demo练手下,那时候其实还没想好要做哪一个类型的,也看了些动漫的,小说阅读, ...

  6. Redux 核心概念

    http://gaearon.github.io/redux/index.html ,文档在 http://rackt.github.io/redux/index.html .本文不是官方文档的翻译. ...

  7. 从发布订阅模式到redux(一)

    最近在学习的过程中,学习了一些关于redux的一些知识,学之前用redux,虽然会用但是实现的原理就不是特别清楚,天天沉迷于搬砖 总是这木搬砖也不是个事啊,就准备开始深入了解一些原理性的东西 首先在看 ...

  8. Redux与它的中间件:redux-thunk,redux-actions,redux-promise,redux-saga

    序言 这里要讲的就是一个Redux在React中的应用问题,讲一讲Redux,react-redux,redux-thunk,redux-actions,redux-promise,redux-sag ...

  9. Redux 和 ngrx 创建更佳的 Angular 2

    Redux 和 ngrx 创建更佳的 Angular 2 翻译:使用 Redux 和 ngrx 创建更佳的 Angular 2 原文地址:http://onehungrymind.com/build- ...

随机推荐

  1. JavaScript获取本机IP地址

    <script type="text/javascript"> /** * Get the user IP throught the webkitRTCPeerConn ...

  2. inception - resnet

    只有reduction-A是共用的,只是改了其中的几个参数 linear是线性激活. 结构是一样的

  3. caffe(6) Blob,Layer,Net 以及对应配置文件的编写

    深度网络(net)是一个组合模型,它由许多相互连接的层(layers)组合而成.Caffe就是组建深度网络的这样一种工具,它按照一定的策略,一层一层的搭建出自己的模型.它将所有的信息数据定义为blob ...

  4. 由防止表单重复提交引发的一系列问题--servletRequest的复制、body值的获取

    @Time:2019年1月4日 16:19:19 @Author:QGuo   背景:最开始打算写个防止表单重复提交的拦截器:网上见到一种不错的方式,比较合适前后端分离,校验在后台实现: 我在此基础上 ...

  5. MIBTree

    NETWORK-APPLIANCE-MIB http://www.mibdepot.com/cgi-bin/getmib3.cgi?abc=0&n=NETWORK-APPLIANCE-MIB& ...

  6. 进程:linux用户态-内核态

    用户态:Ring3运行于用户态的代码则要受到处理器的诸多检查,它们只能访问映射其地址空间的页表项中规定的在用户态下可访问页面的虚拟地址,且只能对任务状态段(TSS)中I/O许可位图(I/O Permi ...

  7. [Recompose] Refactor React Render Props to Streaming Props with RxJS and Recompose

    This lesson takes the concept of render props and migrates it over to streaming props by keeping the ...

  8. 一个工作快八年的老IT人士这几年沉浮总结的职场经验教训

    曾经我挺喜欢写博客,认为把心中的想法表达出来非常畅快.而且还能和网上非常多人沟通交流,如今我更喜欢把想法留在心中.博客非常久没更新了,刚才闲来无事.看看职场话题版块发现非常多人都挺迷茫的,所以我写一些 ...

  9. vue.2.0-自定义全局组件

    App.vue <template> <div id="app"> <h3>welcome vue-loading</h3> < ...

  10. IComparable接口实现自定义类型的排序

    IComparable接口实现自定义类型的排序   CompareTo(Object) 方法的实现必须返回有三个值之一 如下表中所示. 返回值 参数比较 大于0 x>y 等于0 x=y 小于0 ...