废话不多说,直接上干货:
首先说下middleware怎么用
store = createStore(reducer, applyMiddleware(middleware, middleware2));
下面先来看createStore里面干了什么,直接上源码(去除了里面的方法)
export default function createStore(reducer, preloadedState, enhancer) {
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.'
)
}
//这里主要做了一下参数处理,让enhancer正确指向applyMiddleware返回的函数
if (typeof preloadedState === 'function' && typeof enhancer === 'undefined') {
enhancer = preloadedState
preloadedState = undefined
}
if (typeof enhancer !== 'undefined') {
if (typeof enhancer !== 'function') {
throw new Error('Expected the enhancer to be a function.')
}
//这里直接调用了applyMiddleware返回方法
return enhancer(createStore)(reducer, preloadedState)
}
if (typeof reducer !== 'function') {
throw new Error('Expected the reducer to be a function.')
}
let currentReducer = reducer
let currentState = preloadedState
let currentListeners = []
let nextListeners = currentListeners
let isDispatching = false
//没有使用中间件的话直接返回store
return {
dispatch,
subscribe,
getState,
replaceReducer,
[$$observable]: observable
}
}
看了上面createStore的源码,我们有两个结论:
1.在没有使用中间件的时候,我们的createStore直接返回了一个store对象
2.在使用了中间件的时候我们的createStore直接调用了applyMiddleware返回的方法
问题:
在使用中间件的时候store在哪创建的?
别着急,下面我们来看applyMiddleware里面做了什么
export default function applyMiddleware(...middlewares) {
return createStore => (...args) => {
const store = createStore(...args)
let dispatch = () => {
throw new Error(
'Dispatching while constructing your middleware is not allowed. ' +
'Other middleware would not be applied to this dispatch.'
)
}
const middlewareAPI = {
getState: store.getState,
dispatch: (...args) => dispatch(...args)
}
const chain = middlewares.map(middleware => middleware(middlewareAPI))
dispatch = compose(...chain)(store.dispatch)
return {
...store,
dispatch
}
}
}
果然applyMiddleware返回一个方法(这里是一个柯里化的写法)
在上面我们说过在使用中间件的时候createStore执行的是一个applyMiddleware返回的方法,
并传入了两个参数
return enhancer(createStore)(reducer, preloadedState)
return createStore => (...args) => {}
再结合源码,都对上了此时createStore对应的是上面传进来的createStore,...args对应的是上面传入的
(reducer, preloadedState)
接着看这里
//这个时候再调用createStore由于第二个参数不是一个方法,而且也不存在第三个参数,所以直接返回了store
const store = createStore(...args)
原来store是在这个地方创建的,这里存在一个很隐蔽的递归调用,终于知道了(松了一口气)