-
Notifications
You must be signed in to change notification settings - Fork 0
Open
Labels
Description
Redux 源码解析
所有的解析都是结合源码的,我会以注释的形式写上自己的理解
文章中的源码,因为和整体理解 redux 的流程无关,有些部分我删除掉了(比如报错啊这些)
redux 的用法
//我随便找了个我的项目中使用的redux
import { createStore, applyMiddleware, compose } from 'redux';
import rootReducer from './rootReducer';
import createSagaMiddleware from 'redux-saga';
import rootSaga from './rootSaga';
const sagaMiddleware = createSagaMiddleware();
const middlewares = [sagaMiddleware];
if (process.env.NODE_ENV === 'development') {
const { createLogger } = require('redux-logger');
const logger = createLogger({ collapsed: true });
middlewares.push(logger);
}
export default function configureStore(initialState) {
const store = createStore(
rootReducer,
initialState,
compose(applyMiddleware(...middlewares)),
);
sagaMiddleware.run(function* () {
yield rootSaga();
});
if (module.hot) {
module.hot.accept('./rootReducer', () => {
const nextRootReducer = require('./rootReducer').default;
store.replaceReducer(nextRootReducer);
});
}
return store;
}combineReducers
//reducers我们一般的写法就是个对象,value就是一个reducer函数
function combineReducers(reducers) {
//获取所有reducer的key
var reducerKeys = Object.keys(reducers);
//存储过滤后的reducer
var finalReducers = {};
for (var i = 0; i < reducerKeys.length; i++) {
var key = reducerKeys[i];
//将非函数的reducer过滤
if (typeof reducers[key] === 'function') {
finalReducers[key] = reducers[key];
}
}
//获取过滤后的key
var finalReducerKeys = Object.keys(finalReducers);
//返回一个函数接受一个原state和一个action
return function combination(state, action) {
//判断state是否为undefined
if (state === void 0) {
state = {};
}
//state经过计算对比后是否改变
var hasChanged = false;
//计算过后的新的state
var nextState = {};
//循环执行所有的reducer
for (var _i = 0; _i < finalReducerKeys.length; _i++) {
var _key = finalReducerKeys[_i];
var reducer = finalReducers[_key];
//之前的局部state
var previousStateForKey = state[_key];
//计算过后的局部state
var nextStateForKey = reducer(previousStateForKey, action);
nextState[_key] = nextStateForKey;
//比较之前的局部state和计算过后的局部state是否相等
//这里可以看出是直接比较两个对象
//如果在原来的对象上修改state那么对象的指针没有改变,无论你怎么改state中的数据都是相等的
//这就是reducer中必须返回一个新的对象的原因
hasChanged = hasChanged || nextStateForKey !== previousStateForKey;
}
//根据hasChanged结果判断返回旧的state还是新的state
hasChanged =
hasChanged || finalReducerKeys.length !== Object.keys(state).length;
return hasChanged ? nextState : state;
};
}compose
然后我们来看下这段代码
const store = createStore(
rootReducer,
initialState,
compose(applyMiddleware(...middlewares)),
);分析下 compose 函数
我们先从最里面来分析解读,那么就从 compose 入手吧
我们先通过下面这段代码看看 compose 做了什么
let funcs = [f1, f2, f3];
funcs.reduce((preValue, fn) => {
return (...args) => {
return preValue(fn(...args));
};
});
//第一次循环的时候reduce函数没有指定initialValue,那么第一次循环会跳过
//第二次循环的时候preValue就会是f1(如果对reduce这个api不熟悉可以去看下文档)
let loop2ReturnVal = (...args) => {
return f1(f2(...args));
};
//第三次循环
let loop3ReturnVal = (...args) => {
return loop2ReturnVal(f3(...args));
};
//将loop2ReturnVal带入执行
let loop3ReturnVal = (...args) => {
return f1(f2(f3(...args)));
};
//所以compose的作用就是实现函数的嵌套调用
//将传入的函数从右边到左边依次调用redux 中 compose 的源码
function compose() {
for (
var _len = arguments.length, funcs = new Array(_len), _key = 0;
_key < _len;
_key++
) {
funcs[_key] = arguments[_key];
}
if (funcs.length === 0) {
return function (arg) {
return arg;
};
}
if (funcs.length === 1) {
return funcs[0];
}
return funcs.reduce(function (a, b) {
return function () {
return a(b.apply(void 0, arguments));
};
});
}我相信根据上面的分析你已经知道了 compose 是来做什么的
那么我们来分析下上面的 compose 返回了什么
compose(applyMiddleware(...middlewares))
//由上面的源码我们可以看出,compose只传入一个函数返回的是函数本身
//感觉compose没起到什么作用,我们传入两个函数试试
compose(applyMiddleware(...middlewares),(f)=>{return f})
//这个函数最终返回的是
function(...args){
return applyMiddleware(...middlewares)((f)=>{return f}(...args))
}
//那第二个函数为什么要接收一个参数并且要把这个参数返回出去呢?
//我们可以在createStore这个函数的源码中找到答案CreateStore:第一部分
createStore 我们分两部分来看
现在先分析第一部分
function createStore(reducer, preloadedState, enhancer) {
var _ref2;
//下面这两个判断传参的问题
//一般第二个preloadedState我们都没有传
//enhancer的位置一般就传的compose函数
if (
(typeof preloadedState === 'function' && typeof enhancer === 'function') ||
(typeof enhancer === 'function' && typeof arguments[3] === 'function')
) {
throw new Error(
'It looks like you are passing several store enhancers to ' +
'createStore(). This is not supported. Instead, compose them ' +
'together to a single function.',
);
}
if (typeof preloadedState === 'function' && typeof enhancer === 'undefined') {
enhancer = preloadedState;
preloadedState = undefined;
}
//可以看出是先给enhancer函数传入一个createStore并执行
//然后再给enhancer函数执行后的返回值传入reducer、preloadedState这两个参数并执行
if (typeof enhancer !== 'undefined') {
//给enhancer传入一个createStore参数
return enhancer(createStore)(reducer, preloadedState);
}
........
//这一部分的代码主要是定义了一些方法,我们在下一部分解析
........
//最后return出去了一个_ref2对象
//里面有dispatch、subscribe、getState、replaceReducer、$$observable这些方法
return (
(_ref2 = {
dispatch: dispatch,
subscribe: subscribe,
getState: getState,
replaceReducer: replaceReducer,
}),
(_ref2[$$observable] = observable),
_ref2
);
}根据上面我们的分析
//enhancer函数
function(...args){
return applyMiddleware(...middlewares)((f)=>{return f}(...args))
}
//可以看到(f)=>{return f}这个函数相当于直接传递了createStore
//这是因为applyMiddleware需要接收createStore(下面我们会讲到)
//那么enhancer(createStore)的执行结果就是
applyMiddleware(...middlewares)(createStore)
//enhancer(createStore)(reducer, preloadedState)的结果就是
applyMiddleware(...middlewares)(createStore)(reducer,preloadedState)applyMiddleware
function applyMiddleware() {
//获取传入的中间件
//比如说这里我们传入的是saga
//createSagaMiddleware()
for (
var _len = arguments.length, middlewares = new Array(_len), _key = 0;
_key < _len;
_key++
) {
middlewares[_key] = arguments[_key];
}
//这里是个函数的curry化
//可以看到这个地方接收一个createStore然后返回一个参数
return function (createStore) {
return function () {
var store = createStore.apply(void 0, arguments);
var _dispatch = function dispatch() {
throw new Error(
'Dispatching while constructing your middleware is not allowed. ' +
'Other middleware would not be applied to this dispatch.',
);
};
var middlewareAPI = {
getState: store.getState,
dispatch: function dispatch() {
return _dispatch.apply(void 0, arguments);
},
};
var chain = middlewares.map(function (middleware) {
return middleware(middlewareAPI);
});
_dispatch = compose.apply(void 0, chain)(store.dispatch);
// _objectSpread2对象展开符的polyfill
return _objectSpread2({}, store, {
dispatch: _dispatch,
});
};
};
}那么接下来我们带入这段代码中执行
// applyMiddleware(...middlewares)(createStore)(reducer,preloadedState)
//相当于执行下面的函数
function () {
//创建了一个store
//返回值就是上面说到的
/*{
* dispatch: dispatch,
* subscribe: subscribe,
* getState: getState,
* replaceReducer: replaceReducer
* $$observable: observable
*}
*/
var store = createStore.apply(void 0, arguments);
//创建了一个dispatch函数
var _dispatch = function dispatch() {
throw new Error('Dispatching while constructing your middleware is not allowed. ' + 'Other middleware would not be applied to this dispatch.');
};
var middlewareAPI = {
getState: store.getState,
dispatch: function dispatch() {
return _dispatch.apply(void 0, arguments);
}
};
//将上面的middlewareAPI为参数传入middleware中执行
//我们结合一下saga的源码看一下
var chain = middlewares.map(function (middleware) {
return middleware(middlewareAPI);
});
//经过下面的saga分析
//我们可以得出
//chain就变成了,因为下面要用到compose,所以我加了一个函数,让compose的结果看起来更加直观
chain=[function (next) {
return function (action) {
if (sagaMonitor && sagaMonitor.actionDispatched) {
sagaMonitor.actionDispatched(action);
}
var result = next(action); // hit reducers
sagaEmitter.emit(action);
return result;
};
},
function(next){
return function(action){
// ...
// 中间件处理逻辑
// ...
return next(action)
}
}
]
//上面那个chain是我为了看起来方便,实际上源码里面并没有哈
//compose功能跟上面相同,从右到左依次执行函数
_dispatch = compose.apply(void 0, chain)(store.dispatch);
//最后返回一个有被中间件扩展功能后的dispatch的store
return _objectSpread2({}, store, {
dispatch: _dispatch
});
//这下我们可以得出一个结论,中间件其实是丰富了dispatch的功能
//每次dispatch一个action,都会经过中间件的层层处理
//而且可以初略的对洋葱模型有个认识
//compose的时候是从里到外绑定中间件
//执行的时候是从外到里执行
//这里有点绕 可以自己理一下体会一下,我也想了老半天
}(reducer,preloadedState)saga 中间件的创建函数
//代码中是这样使用的
const sagaMiddleware = createSagaMiddleware();
//createSagaMiddleware的源码
function sagaMiddlewareFactory() {
//返回来了一个函数
//接收一个_ref2参数
//也就是上面的middlewareAPI
function sagaMiddleware(_ref2) {
var getState = _ref2.getState,
dispatch = _ref2.dispatch;
....
//中间是saga中间件的一堆逻辑
....
//getState和dispatch都没有在返回的函数中用到,只是在中间件自己的处理逻辑中用到
return function (next) {
return function (action) {
if (sagaMonitor && sagaMonitor.actionDispatched) {
sagaMonitor.actionDispatched(action);
}
var result = next(action); // hit reducers
sagaEmitter.emit(action);
return result;
};
};
}
return sagaMiddleware;
}CreateStore:第二部分
function createStore(reducer, preloadedState, enhancer) {
......
var currentReducer = reducer;
var currentState = preloadedState;
var currentListeners = [];
var nextListeners = currentListeners;
var isDispatching = false;
//这是个工具函数
//用来判断currentListeners和nextListeners的指针是否一样,如果一样,那么就复制一个新的nextListeners
function ensureCanMutateNextListeners() {
if (nextListeners === currentListeners) {
nextListeners = currentListeners.slice();
}
}
//获取当前的state
function getState() {
//如果是dispatching状态的话就抛出错误
if (isDispatching) {
throw new Error(
'You may not call store.getState() while the reducer is executing. ' +
'The reducer has already received the state as an argument. ' +
'Pass it down from the top reducer instead of reading it from the store.',
);
}
return currentState;
}
function subscribe(listener) {
//判断listener是不是个函数
if (typeof listener !== 'function') {
throw new Error('Expected the listener to be a function.');
}
//判断是否是在dispatching状态
if (isDispatching) {
throw new Error(
'You may not call store.subscribe() while the reducer is executing. ' +
'If you would like to be notified after the store has been updated, subscribe from a ' +
'component and invoke store.getState() in the callback to access the latest state. ' +
'See https://redux.js.org/api-reference/store#subscribelistener for more details.',
);
}
var isSubscribed = true;
ensureCanMutateNextListeners();
nextListeners.push(listener);
//返回一个解除监听的函数
return function unsubscribe() {
if (!isSubscribed) {
return;
}
if (isDispatching) {
throw new Error(
'You may not unsubscribe from a store listener while the reducer is executing. ' +
'See https://redux.js.org/api-reference/store#subscribelistener for more details.',
);
}
isSubscribed = false;
ensureCanMutateNextListeners();
var index = nextListeners.indexOf(listener);
nextListeners.splice(index, 1);
currentListeners = null;
};
}
function dispatch(action) {
//判断action的值
if (!isPlainObject(action)) {
throw new Error(
'Actions must be plain objects. ' +
'Use custom middleware for async actions.',
);
}
if (typeof action.type === 'undefined') {
throw new Error(
'Actions may not have an undefined "type" property. ' +
'Have you misspelled a constant?',
);
}
if (isDispatching) {
throw new Error('Reducers may not dispatch actions.');
}
//更新state
try {
isDispatching = true;
currentState = currentReducer(currentState, action);
} finally {
isDispatching = false;
}
var listeners = (currentListeners = nextListeners);
//循环执行监听函数
for (var i = 0; i < listeners.length; i++) {
var listener = listeners[i];
listener();
}
return action;
}
//替换reducer
function replaceReducer(nextReducer) {
if (typeof nextReducer !== 'function') {
throw new Error('Expected the nextReducer to be a function.');
}
currentReducer = nextReducer;
dispatch({
type: ActionTypes.REPLACE,
});
}
//用于初始化state,因为这个action都会直接命中reducer中的default分支
dispatch({
type: ActionTypes.INIT,
});
return (
(_ref2 = {
dispatch: dispatch,
subscribe: subscribe,
getState: getState,
replaceReducer: replaceReducer,
}),
(_ref2[$$observable] = observable),
_ref2
);
}