Redux原始碼解讀(二)
上篇文章我們分析了createStore和combineReducers檔案,這一篇我們分析剩下的檔案。
首先是bindActionCreators檔案,這個檔案十分簡單
function bindActionCreator(actionCreator, dispatch) {
return function() {
return dispatch(actionCreator.apply(this, arguments))
}
}
上面的高階函式是在檔案內部中使用,這個是為了減少重複程式碼,返回的函式中的引數傳給的actionCreator函式執行,然後dispatch將其返回值作為引數再執行,其返回值作為該函式的返回值。
export default function bindActionCreators(actionCreators, dispatch) {
if (typeof actionCreators === 'function') {
return bindActionCreator(actionCreators, dispatch)
}
if (typeof actionCreators !== 'object' || actionCreators === null) {
throw new Error(
`bindActionCreators expected an object or a function, instead received ${
actionCreators === null ? 'null' : typeof actionCreators
}. ` +
`Did you write "import ActionCreators from" instead of "import * as ActionCreators from"?`
)
}
const keys = Object.keys(actionCreators)
const boundActionCreators = {}
for (let i = 0; i < keys.length ; i++) {
const key = keys[i]
const actionCreator = actionCreators[key]
if (typeof actionCreator === 'function') {
boundActionCreators[key] = bindActionCreator(actionCreator, dispatch)
}
}
return boundActionCreators
}
這個函式很簡單,其中第一個引數既可以是函式也可以是物件,如果是函式,則直接返回bindActionCreator處理後的函式,若為物件,則通過迴圈其key值遞迴找到每一個對應的ActionCreator,最後返回一個相應的物件。
也就是說,如果輸入的是函式,則返回的是函式,若輸入的是物件,則返回的也是物件。
接下來我們看compose檔案(其實這個檔案只是一個工具函式)
export default function compose(...funcs) {
if (funcs.length === 0) {
return arg => arg
}
if (funcs.length === 1) {
return funcs[0]
}
return funcs.reduce((a, b) => (...args) => a(b(...args)))
}
當compose引數為空時,則返回一個函式,該函式直接返回其引數
若引數為一個時,則直接返回該引數(該引數應當是一個函式)
若引數為多個時,則通過reduce進行累計,返回一個函式,該函式內部是一層一層函式的疊加,該函式引數在疊加的最內層呼叫。舉個栗子�
compose(f, g, h)就意味著
返回(...args) => f(g(h(...args)))
而compose函式在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.`
)
}
let chain = []
const middlewareAPI = {
getState: store.getState,
dispatch: (...args) => dispatch(...args)
}
chain = middlewares.map(middleware => middleware(middlewareAPI))
dispatch = compose(...chain)(store.dispatch)
return {
...store,
dispatch
}
}
}
該函式接收多個函式作為引數,然後返回一個函式,該函式又返回一個函式(說真的不喜歡這樣的千層餅。。。),而這個函式則返回解散的store和dispatch
在最內層的函式立刻,首先通過createSotre建立了一個store,然後定義了一個奇葩版的dispatch,也就是說在使用中介軟體裡嚴禁呼叫dispatch
然後通過map將state和奇葩版的dispatch傳入中介軟體,最後通過compose將其dispatch作為千層餅最內層被中介軟體一層一層的裹起來,這樣日後呼叫dispatch就必然會呼叫一層一層的中介軟體。(dispatch的結果作為引數),最後將這些值作為返回值
最後是我自己寫的一個超簡易版redux,功能不及正版redux強大,但勝在簡單,有興趣的朋友可以看一下
redux的內容在redux資料夾內,clone後npm install最後npm start即可