一、createStore函数的参数:
reducer:reducer是一个函数,该函数会返回一个全新的state,而state则保存了所有的数据
preloadedState:初始state
enhancer:这个参数特别有意思,如果该enhancer参数存在的话,会将当前的createStore
函数作为参数传入enhancer函数,并且,enhancer执行之后得到一个新函数,该新函数其实
就是一个加强版的createStore函数,新的函数会把之前的reducer和preloadeState作为参数
传入并执行。这个enhancer参数为redux中间件提供了入口。
createStore 的函数的作用就是生成一个 store 对象,这个对象具有5个方法:
return {
dispatch, // 传入 action,调用 reducer 及触发 subscribe 绑定的监听函数
subscribe,
getState,
replaceReducer, // 用新的 reducer 代替当前的 reducer,使用不多
[$$observable]: observable
}
而 applyMiddleware 函数的作用就是对 store.dispatch 方法进行增强和改造,使得在发出 Action 和执行 Reducer 之间添加其他功能。
compose 函数则是 applyMiddleware 函数的核心,其会形成串联的函数调用关系,用于增强 dispatch 方法。
- 模块之间的调用关系
(i) 首先,createStore 模块会对传入的参数进行判断,分别处理不同参数的情况,当传入 applyMiddleware(...middleware) 的时候,就会返回 applyMiddleware(...middleware) 执行之后的高阶函数,即:
// createStore.js
if (typeof enhancer !== 'undefined') {
if (typeof enhancer !== 'function') {
throw new Error('Expected the enhancer to be a function.')
}
// 这里的 enhancer 是 applyMiddleware(...) 执行后的高阶函数,传参无 enhancer
return enhancer(createStore)(reducer, preloadedState)
}
(ii)然后,就进入了 applyMiddleware 模块内部的逻辑,从 createStore 返回的高阶函数,其传入的参数是没有 enhancer 的,因此走的是 createStore 函数中没有传入 enhancer 的逻辑,用于先获得没有中间件时返回的 store。
// applyMiddleware.js
export default function applyMiddleware(...middlewares) {
return (createStore) => (reducer, preloadedState, enhancer) => {
const store = createStore(reducer, preloadedState, enhancer)
let dispatch = store.dispatch
let chain = [] // 用于存放获取了store的中间件数组
const middlewareAPI = {
getState: store.getState,
dispatch: (...args) => dispatch(...args)
}
chain = middlewares.map(middleware => middleware(middlewareAPI))
dispatch = compose(...chain)(store.dispatch)
return {
...store,
dispatch
}
}
}
(iii)接着,获取最原始的 store 的 getState 和 dispatch,封装于 middlewareAPI 对象。将该对象传入中间件 middleware 中,形成中间件数组 chain。
其中,middleware 的范式是:(store) => (next) => (action) => {},将 middlewareAPI 传入middleware 后,
中间件便获得了 {getState, dispacth}。至此,chain 中间件数组中包含的每个中间件的形式都变成
了 (next) => (action) => {} 的形式。
(iiii)最后,调用 compose 函数,如 chian = [middleware1, middleware2, middleware3],则 dispatch = compose(...chain)(store.dispatch),即执行 middleware1(middleware2(middleware3(store.dispatch))),然后赋值给 dispatch。
总之,不管是否有 applyMiddleware,createStore 的结果都是输出一个 store 对象,而 applyMiddleware 则可以对 store 对象中的 dispatch 进行改造。