function createStore(reducer, preloadedState, enhancer) {
var _ref2;
// 判断,如果只有两个参数,且第二个参数还是一个function
if (typeof preloadedState === 'function' && typeof enhancer === 'undefined') {
enhancer = preloadedState;
preloadedState = undefined;
}
// 如果三个参数都传了,且第三个参数还是一个function
if (typeof enhancer !== 'undefined') {
if (typeof enhancer !== 'function') {
throw new Error('Expected the enhancer to be a function.');
}
return enhancer(createStore)(reducer, preloadedState);
}
if (typeof reducer !== 'function') {
throw new Error('Expected the reducer to be a function.');
}
// ... 省略
// subscribe 注册一个监听,注意 listener 必须是一个function
function subscribe(listener) {
if (typeof listener !== 'function') {
throw new Error('Expected listener to be a function.');
}
var isSubscribed = true;
ensureCanMutateNextListeners();
// 将 监听方法添加到 nextListeners 队列中
nextListeners.push(listener);
// 返回了一个 unsubscribe 的方法,如果我们要取消订阅,那么就可以调用这个 unsubscribe
return function unsubscribe() {
if (!isSubscribed) {
return;
}
isSubscribed = false;
ensureCanMutateNextListeners();
var index = nextListeners.indexOf(listener);
nextListeners.splice(index, 1);
};
}
function dispatch(action) {
// ... 省略
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;
}
// createStore 在初始化的时候就会执行一次 dispatch ,
// When a store is created, an "INIT" action is dispatched so that every
// reducer returns their initial state. This effectively populates
// the initial state tree.
dispatch({ type: ActionTypes.INIT });
// ... 省略
redux 原理
单一数据源,即项目的数据源只有一个,整个应用的数据都保存在一个js对象中,这样我们的页面之间或者不同组件之间可以进行数据的共享。redux的核心就是store,redux中的
createStore
方法会根据reducer
返回store,而且createStore
暴露出一些方法方便我们使用getState
获取store中的数据dispatch
触发一个actionsubscribe
注册一个监听,当store发生变化的时候调用replaceReducer
更新当前store中的reducercreateStore
直接上源码,已经在源码中做了注释
其实createStore 在初始化的时候就会执行一次 dispatch,这也是为什么我们可以不传 preloadedState 这个参数,createStore还可以构建出state的结构。 但是这需要一个前提条件:
在定义reduer函数的是的时候,在没有匹配到action后,仍然需要返回一个state的默认值(不能位undefined)
。如果我们没有返回默认状态的系统会给我们报一个错,让我们必须返回默认状态的state, 看下面实例redux 中间件原理
我们来看看applyMiddleware.js的源码
我们注意看上面的代码中middlewareAPI里面的
dispatch
方法,该方法又返回了一个_dispatch
函数,也就是说当中间中使用middlewareAPI.dispatch
时候,最后调用的还是_dispatch
函数 。这就像是一个闭包一样。接下来在看看compose.js的源码
其实compose函数中最重要最难懂的地方就是
reduce
高阶函数了。可以点这里学习一下。每个中间件都是这种模型({dispatch, getState}) => (next) => action
,在applyMiddleware方法中每个中间件都会接受middlewareAPI
作为第一个参数返回一个新的函数(接下来我用one,two,three这三个函数来模拟返回的函数),并作为变量chain
集合中的一个元素,最后传给compose函数。compose(one, two, three)(dispatch)
方法合成以后,返回one(two(three.apply(undefined, dispatch)))
baz
的函数,且函数中的next
其实就是我们传递的dispatch
参数bar
的函数,且函数中的next
其实就是three返回的baz
函数foo
的函数,且函数中的next
其实就是two返回的bar
函数最后disp其实就是函数
foo
,且函数接受action
作为参数,中间件执行的原理就是这样,action会从在中间件之间传递,一直传达到store.dispatch,然后触发action。我们再来看看redux-thunk
我们再看看,如何定义action行为
this.props.dispatch(addCountAsync(...args))
。在dispatch的时候action执行了,并返回了一个函数,我们暂且将这个返回函数命名为funcreturn action(dispatch, getState, extraArgument)
(并不再往下一个中间件传递action),那不就等于func(dispatch, getState, extraArgument)
,dispatch
,而这个dispatch就是中间件接收的middlewareAPI参数中的dispatch属性,最终还是调用的中间件合成的_dispatch函数
,那么ation就会继续往下执行了,直到传到store.dispatch。注意上面有个问题,就是action想要在中间件之间依次传递,那么必须是由中间件合成的dispatch触发的action才可以。否则就会立即出发这个action行为(注意:传递给store.dispatch函数的action必须是一个简单对象)。
combineReducers
我们先来看看它是怎么使用的
也就是说combineReducers可以将多个子reducers合并成一个reducer,现在我们来看看它的源码
bindActionCreators