redux8 - redux 中間件 和 applyMiddleware 及其實現原理

參考redux倉庫, redux-logger庫
所有1-8系列代碼倉庫

  • 新建個項目吧 - 引入 redux, react-redux

中間件執行流程圖


在這裏插入圖片描述


演示代碼倉庫
在這裏插入圖片描述
就這個演示了,點擊 + 1 ,現在呢, 我想打印個日誌,就是每次點擊按鈕,都能打印出老的狀態和新的狀態

  • 理邏輯,既然是在每次點擊事件之後打印,那麼,如果想拿到老的狀態,就需要在派發前,想拿到新的狀態,就是在派發後
    先這樣寫:
let store = createStore(reducers);
let dispatch = store.dispatch;
store.dispatch = function(action) {
  console.log(`老值: ${JSON.stringify(store.getState())}`);
  dispatch(action);
  console.log(`新值:${JSON.stringify(store.getState())}`);
};
export default store

這樣一來已經實現了,那上邊的代碼,核心就是重寫 了reduxdispatch方法,

  1. 先存起來一份老的, 用於用戶的派發action
  2. 再重寫一份 dispatch 方法, 用於,在派發前和派發後做某些事
  • 接着整個異步邏輯,點擊延時1秒再加1, 接着重寫 dispatch, 1秒後,再派發action
store.dispatch = function(action) {
  setTimeout(() => {
    dispatch(action);
  }, 1000);
};

參考logger的實現第67行開始, 可以看到 連續返回了3個函數, 同時,第一個參數拿到getState, 第二個參數傳入老的 dispatch, 第三個參數就是reducer,接着實現一個簡化版logger中間件
在這裏插入圖片描述

function logger({ getState }) {
  return function(next) {
    return function(action) {
      console.log(`老值: ${JSON.stringify(getState())}`);
      next(action);
      console.log(`新值: ${JSON.stringify(getState())}`);
    };
  };
}
let store = applyMiddleware(logger)(createStore)(reducers)

在這裏插入圖片描述
好了, 來接着推導 applyMiddleware 方法, 它接收的參數有 自己寫的 logger 中間件, redux的 createStore方法, 還有自己的reducer, 它連續返回了3個函數, 代碼實現就是下邊這樣的

// 傳入自己的中間件
function applyMiddleware(middleWare) {
  // 傳入 redux 的 createStore 方法
  return function(createStore) {
  	// 傳入自己的reducer
    return function(reducer) {
     	let store = createStore(reducer);
     	// 包裹了一圈, 最後還是返回了 store因爲外部要接收store對象
     	// 此時,還沒有處理 中間件 middleWare 參數
      	return store;
    };
  };
}

處理 傳入的 middleWare參數 (也就是中間件)
在這裏插入圖片描述

function applyMiddleware(middleWare) {
  // 傳入 redux 的 createStore 方法
  return function(createStore) {
  	// 傳入自己的reducer
    return function(reducer) {
     	let store = createStore(reducer);
     	// 處理middleWare 參數, 看着上邊的 logger 函數寫
     	// 1. 先執行第一次傳入 store 實參, 供 logger 組件解構出 getState 參數
     	middleWare = middleWare(store)
     	// 再執行第二次 傳入 dispatch 供 next 使用派發action
     	let dispatch = middleWare(store.dispatch)
     	// 將這個與 store的 dispatch 進行替換掉
      	return {
			...store,
			dispatch
		};
    };
  };
}

打印,實現了 單一中間件的處理,但實際開發中,中間件可能有多個的,下篇再接着聊
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章