1. Redux簡介
- Redux的核心API主要有兩個:createStore和reducer。
- createStore
createStore(reducers[, initialState])主要是用于生成store的,reducers必須傳入,initialState是可選擇是否傳入的參數(shù)初始化狀態(tài)。引用時:
其中創(chuàng)建的store又包含四個API:import { createStore } from 'redux'; const store = createStore(reducers);
- getState():獲取 store 中當前的狀態(tài)。
- dispatch(action):分發(fā)一個 action,并返回這個 action,這是唯一能改變 store 中數(shù)據(jù)的方式。
- subscribe(listener):注冊一個監(jiān)聽者,它在 store 發(fā)生變化時被調(diào)用。
- replaceReducer(nextReducer):更新當前 store 里的 reducer,一般只會在開發(fā)模式中調(diào)用該方法。
- reducer
reducer主要負責響應(yīng)action并修改數(shù)據(jù), 它是一個函數(shù),reducer(previousState, action) => newState,需要注意的是第一次執(zhí)行的時候,并沒有任何的 previousState,因此在這種特殊情況下需要返回一個定義好的 initialState。實際運用時:const initialState = { todos: [], }; function todos(previousState = initialState, action) { switch (action.type) { case 'XXX': { // 具體的業(yè)務(wù)邏輯 } default: return previousState; } }
- 與React的綁定
react-redux庫提供了一個組件<Provider/>和一個方法connect()幫助 Redux 和 React 進行綁定。Provider 是整個應(yīng)用最外層的 React 組件,它接受一個 store 作為 props。connect() 可以在整個React應(yīng)用的任意組件中獲取store中的數(shù)據(jù)。
2.Redux中間件
2.1 什么是中間件
傳統(tǒng)的Redux單向數(shù)據(jù)流如圖所示:

這樣的單向數(shù)據(jù)流動存在很多問題,比如當調(diào)用的action發(fā)生改變時,就必須修改dispatch 或者 reducer,而且請求數(shù)據(jù)不是異步的,因此Redux中間件由此出現(xiàn),它的自由組合,自由插拔的插件機制正好解決了這個問題,它的目的是增強dispatch,Redux運用中間件處理事件的流程如圖所示:

需要注意的是這些中間件會按照指定的順序一次處理傳入的action,只有排在前面的中間件完成任務(wù)之后,后面的中間件才有機會繼續(xù)處理 action。
2.2 中間件機制
Redux是通過applyMiddleware方法來加載中間件的,因此我們首先來看一下applyMiddleware方法的源碼
//compose 可以接受一組函數(shù)參數(shù),從右到左來組合多個函數(shù),然后返回一個組合函數(shù)。
import compose from './compose';
export default function applyMiddleware(...middlewares) {
return (next) => (reducer, initialState) => {
//為中間件分發(fā)store
let store = next(reducer, initialState);
let dispatch = store.dispatch;
let chain = [];
//將store 的 getState方法和 dispatch 方法賦值給middlewareAPI
var middlewareAPI = {
getState: store.getState,
//使用匿名函數(shù),保證最終compose 結(jié)束后的新dispatch保持一致
dispatch: (action) => dispatch(action),
};
//chain: [f1, f2, ... , fx, ..., fn]
chain = middlewares.map(middleware => middleware(middlewareAPI));
//利用compose將所有中間件串聯(lián)起來,
dispatch = compose(...chain)(store.dispatch);
return {
...store,
dispatch,
};
}
}
其中 compose就是將傳入的所有函數(shù)組合成一個新的函數(shù),Redux中的compose實現(xiàn)方式如下所示:
function compose(...funcs) {
return arg => funcs.reduceRight((composed, f) => f(composed), arg);
}
當調(diào)用 reduceRight時依次從 funcs 數(shù)組的右端取一個函數(shù) fn 拿來執(zhí)行,fn的參數(shù) composed 就是前一次 f(n+1) 執(zhí)行的結(jié)果假如n=3,新的 dispatch = f1(f2(f3(store.dispatch))))。
接下來我們看看一個最簡單的中間件是如何實現(xiàn)的:
export default (dispatch, getState) => next => action => next(action)
其中的next是一個函數(shù),當調(diào)用它時,表示一個中間件已經(jīng)完成了任務(wù),然后將這個action傳遞給下一個中間件并作為參數(shù)傳遞給next函數(shù)處理action。
那么使用next(action)和store.dispatch(action)有何區(qū)別呢?簡單的來說store.dispatch(action)都是和新的dispatch一樣的,但是next(action)是進入下一個中間件的操作,所以如果某個中間件使用了store.dispatch(action),就相當于把整個中間件的傳遞過程重頭來一遍。具體如圖所示:
