Redux 版本:3.7.2
Redux 是 JavaScript 状态容器,提供可预测化的状态管理。
说白了Redux就是一个数据存储工具,所以数据基础模型有get方法,set方法以及数据改变后通知的对象subscribe订阅者。
getState: getter(取)
dispatch: setter(存)
subscribe: 订阅
Redux 提供了五个方法
接下来我们来一一解析。
createStore
创建一个 Redux store 来以存放应用中所有的 state。应用中应有且仅有一个 store。
参数:
reducer (Function): 接收两个参数,分别是当前的 state 树和要处理的 action,返回新的 state 树。
[ reloadedState ] (any):初始时的 state。
enhancer (Function):后面再讲。
返回值:
getState:获取store方法
dispatch:修改store方法
subscribe:订阅store变化方法
replaceReducer:重置reducer方法
先来写一个基础的 createStore 如下:
function createStore() { function getState() { } // 取 function dispatch() { } // 存 function subscribe() { } // 订阅 function replaceReducer() { } // 重置reducer return { getState, dispatch, subscribe, replaceReducer } } getStategetState 实现很简单,直接返回 currentState。
function createStore() { let currentState = {}; // 数据 function getState() { // 取 return currentState; } function dispatch() { } // 存 function subscribe() { } // 订阅 function replaceReducer() { } // 重置reducer return { getState, dispatch, subscribe, replaceReducer } } dispatchdispatch 传入 action,通过 action.type 区别操作。
function createStore() { let currentState = {}; function getState() { // 取 return currentState; } function dispatch(action) { // 存 switch (action.type) { case 'PLUS': currentState = { ...currentState, count: currentState.count + 1, }; } return action; } function subscribe() { } // 订阅 function replaceReducer() { } // 重置reducer return { getState, dispatch, subscribe, replaceReducer } }因为 Redux 要通用,所以 dispatch 内和业务相关的代码要提取出来,Redux 给它起了个名字,叫 reducer。
提取reducer,
const initialState = { count: 0, } export default (state = initialState, action) => { switch (action.type) { case 'PLUS': return { ...state, count: state.count + 1, } case 'MINUS': return { ...state, count: state.count - 1, } default: return state } }给 createStore 添加两个参数 reducer, preloadedState。
preloadedState非必传,如果不传,currentState 默认值就是 undefined。
在 createStore 中添加初始化方法 dispatch({ type: '@@redux/INIT' }) ; 初始化的 action.type 必须是 reducer 中没有使用过的,Redux 源码中使用了 '@@redux/INIT'。初始化方法会执行一次 dispatch。
初始化时,如果 currentState 是 undefined, 那么在 reducer 中, state = initialState 会把 initialState 赋值给 state,然后通过 default return 出去, 最后修改 currentState。相当于 currentState = initialState。
最后 createStore 如下
function createStore(reducer, preloadedState) { let currentState = preloadedState; function getState() { // 取 return currentState; } function dispatch(action) { // 存 currentState = reducer(currentState, action); return action; } function subscribe() { } // 订阅 function replaceReducer() { } // 重置reducer dispatch({ type: '@@redux/INIT' }); // 初始化 return { getState, dispatch, subscribe, replaceReducer } }根据代码可以看出,reducer 和 action 都是开发者自定义的,Redux 只是把 reducer 返回的 state 赋值给了 currentState,那么开发者自定义其他格式的action ,并且在 reducer 中作出对应的解析,然后返回 state,当然也是完全可以的。只是 Redux 统一了这种写法,降低了个性化带来的开发成本。
实际上 createStore 还有第三个参数 ,目前用不到,后面再讲。
subscribesubscribe 有一个参数 listener (Function): 每当 dispatch action 的时候都会执行的回调。
subscribe 使用了设计模式中的 发布-订阅模式,又叫 观察者模式。
实现:
在 createStore 中添加一个储存 变化监听器 的数组 currentListeners;
subscribe 将 变化监听器 放入 currentListeners;
每次 dispatch 时, 循环执行 currentListeners 中的 变化监听器。
function createStore(reducer, preloadedState) { let currentState = preloadedState; let currentListeners = []; function getState() { // 取 return currentState; } function dispatch(action) { // 存 currentState = reducer(currentState, action); currentListeners.forEach(fn => fn()); return action; } function subscribe(listener) { // 订阅 currentListeners.push(listener); } function replaceReducer() { } // 重置reducer dispatch({ type: '@@redux/INIT' }); // 初始化 return { getState, dispatch, subscribe, replaceReducer } } replaceReducer重置 reducer, 并不会重置 currentState。
实现:
添加变量 currentReducer;
dispatch 使用 currentReducer;
replaceReducer 方法将 nextReducer 赋值给 replaceReducer, 然后执行 dispatch({ type: '@@redux/INIT' })。