前言
虽然一直使用 redux+react-redux, 但是并没有真正去讲 redux 最基础的部分理解透彻, 我觉得理解明白 redux 会对 react-redux 有一个透彻的理解.
其实, redux 并不只可以用于 react 的, 其实他可以用于任何地方, 其实他的基础原理大概就是发布 / 订阅模式, 此处主要对 redux 的源码进行一个深入的剖析
redux 架构
redux 一共有下边几部分构成:
- * createStore
- * combineReducers
- * bindActionCreators
- * applyMiddleware
- * compose
其中, createStore 分为如下几部分
* subscribe 订阅用于刷新页面的回调事件
* dispatch 触发动作
* getState 获取当前状态下的 store
* replaceReducer 替换初始化传入的 reducer
* Observer 相关, 不太理解如何使用, 暂时略过
store
其实, 最简单的使用如下:
执行这个方法 createStore(reducer) 则会返回暴露上面几个方法的一个对象 (赋值给 store)
通过 store.getState 则可以获取当前 store, 此处注意, 官方文档一直再说要在你定义的 reducer 当中定义一个 default, 来返回默认值, 其实主要是页面需要初始化, 在 createStore.js 可以看出最后他调用了
dispatch({ type: ActionTypes.INIT })
action -> dispatch -> 更新 store
当 dispatch 调用的时候 (一般会在事件的回调函数中调用), 会去执行 reducer(也就是你定义的处理函数), 通过你的处理函数, 最后会返回一个新的 store 来供你更新 redux 缓存的 store, 从这块可以看出
- try {
- isDispatching = true
- // 通过给 reducer 回传当前状态和动作状态来更新 store
- currentState = currentReducer(currentState, action)
- } finally {
- isDispatching = false
- }
- render
前面提到的 store 还有一个方法, subscribe, 这个方法会缓存传入的方法, 便于 dispatch 的时候进行回调, 从而更新试图.
其实, 上面这些就是 redux 的原理了, 具体可以看一下 redux 官方示例, 有一个 couter 的例子, 很容易理解: https://github.com/reactjs/redux/blob/master/examples/counter/src/index.js
下面说一下其他几个点
compose
简单来说就是从右侧函数的返回值, 作为左侧函数的参数
如
compose(fn, fn2)(...args)
等同于 fn(fn2(...args))
applyMiddleware
这个也是挺常用的一个方法
使用方法:
const store = applyMiddleware(Middle1, Middle2)(createStore)(reducer, initialState, enhancer)
这个方法主要做了一件事情
就是利用中间件来改变程序默认创建 store,dispatch 对整个过程做的处理, 从而达到你自己想要的目的
最著名的一个组件就是 redux-thunk, 说这个方法前, 先说说中间件应该怎么写, 官网有这么一段描述
每个 middleware 接受 Store 的 dispatch 和 getState 函数作为命名参数, 并返回一个函数. 该函数会被传入 被称为 next 的下一个 middleware 的 dispatch 方法, 并返回一个接收 action 的新函数, 这个函数可以直接调用 next(action), 或者在其他需要的时刻调用, 甚至根本不去调用它. 调用链中最后一个 middleware 会接受真实的 store 的 dispatch 方法作为 next 参数, 并借此结束调用链. 所以, middleware 的函数签名是 ({ getState, dispatch }) => next => action.
下面看下 redux-thunk 非常简单, 但是他的目的主要是为了再不引入第三方框架可以来操作异步事件, 如
- store.dispatch((dispatch, setState) => {
- setTimeout(() => {
- dispatch({
- type: 'EXAMPLES',
- payoad: '...'
- })
- }, 5);
- })
在 redux-thunk 内部做了这么件事情, 就是如果 action 是函数则执行这个函数, 给他传入 dispatch, getState 及其他参数, 如果不是, 直接调用 next(action), 将控制权交到下一个中间件 (中间件是从左到右执行顺序, 最后控制权交到 store.dispatch), 其实中间件就是在 dispatch 触发之前做了一些其他的事情来扩展 redux 功能
combineReducers
一共做了两件事情, 首先将 reducer 进行检查是否为函数, 同时检测 reducer 默认传入的 store 是否为 undefined 同时检测是否影响到 redux 默认明明空间的 action type; 然后就是返回一个组合 reducer, 里边处理下每次有值改变的时候, 执行该函数 (过程同单个 reducer), 内部其实就是去循环执行他的子 reducer, 子 reducer 根据 action 来进行 store 的修改, 所以来说每个子 reducer 只要有处理相同 type 的函数, 都会起到作用
注意: 如果你的子 reducer 都不返回新对象, 这个方法中会进行判断, 则他也不返回新对象
bindActionCreators
可以将 Action Creator(也就是生成 action 的函数) 绑定到当前函数, 执行后会生成 action, 然后需用 dispatch(action)
没太看懂使用场景, 有了解的欢迎留言, 互相交流学习.
总结
我们常用的一般是除了 bindActionCreators 和 compose 之外的方法, 那个理解明白了, 对于以后出现的问题会有很大帮助, 本文只是针对最基础的 redux 进行解析, 之后有机会继续解析 react-redux 对他的封装
来源: https://segmentfault.com/a/1190000014815318