Redux 是 JavaScript 状态容器,提供可预测化的状态管理。
Redux 有三大原则:应用中所有的 state 都以一个对象树的形式储存在一个单一的 store 中(单一数据源);惟一改变 state 的办法是触发 action( state 是只读的);为了描述 action 如何改变 state 树,需要编写 reducer(使用纯函数来执行修改 state)。
redux 的核心是 createStore 函数,来看下他的简单实现:
function createStore(reducer) {
let listenerIdCounter = 0;
let currentState = undefined;
let currentListeners = new Map();
let nextListeners = currentListeners
let isDispatching = false;
function getState() {
return currentState;
}
function subscribe(listener) {
const listenerId = listenerIdCounter++;
ensureCanMutateNextListeners();
nextListeners.set(listenerId, listener);
return unsubscribe.bind(this, listenerId);
}
function unsubscribe(listenerId) {
ensureCanMutateNextListeners();
nextListeners.delete(listenerId);
}
function disposable(listener) {
const listenerId = listenerIdCounter++;
function _disposable(...args) {
listener.apply(this, args);
unsubscribe(listenerId);
}
ensureCanMutateNextListeners();
nextListeners.set(listenerId, _disposable);
}
function dispatch(action) {
if (isDispatching) {
throw new Error('Reducers may not dispatch actions.');
}
try {
isDispatching = true;
currentState = reducer(currentState, action);
} finally {
isDispatching = false;
}
const listeners = currentListeners = nextListeners;
listeners.forEach((listener) => {
listener();
});
return action;
}
function ensureCanMutateNextListeners() {
if (nextListeners === currentListeners) {
nextListeners = new Map()
currentListeners.forEach((listener, key) => {
nextListeners.set(key, listener)
})
}
}
dispatch({ type: 'INIT' });
return {
getState,
subscribe,
dispatch,
disposable,
};
}
在平时开发中我们还会用到 combineReducers 将多个模块的 state 管理到一棵树上,下面我们看下 combineReducers 到底干了什么:
function combineReducers(reducers) {
const reducerKeys = Object.keys(reducers);
const finalReducers = {};
for (let i = 0; i < reducerKeys.length; i++) {
const key = reducerKeys[i];
if (typeof reducers[key] === 'function') {
finalReducers[key] = reducers[key];
}
}
const finalReducerKeys = Object.keys(finalReducers);
return function combination(state = {}, action) {
let hasChanged = false;
const nextState = {};
for (let i = 0; i < finalReducerKeys.length; i++) {
const key = finalReducerKeys[i];
const reducer = finalReducers[key];
const previousStateForKey = state[key];
const nextStateForKey = reducer(previousStateForKey, action);
nextState[key] = nextStateForKey;
hasChanged = hasChanged || nextStateForKey !== previousStateForKey;
}
hasChanged = hasChanged || finalReducerKeys.length !== Object.keys(state).length;
return hasChanged ? nextState : state;
}
}
总结:
Redux 其实就是运用了发布订阅模式对数据对象进行管理的函数