redux中間件詳解

  • 回顧redux

    • redux解決了什么問題
    • redux基本架構(gòu)圖
    • dispatch函數(shù)
  • 如何編寫中間件

    • 中間件函數(shù)基本格式
    • 中間件洋蔥模型
  • redux中間件源碼解析

    • applyMiddleware函數(shù)
    • compose函數(shù)

1. 回顧redux

  • redux解決了什么問題

    • 一個react應(yīng)用就是一顆組件樹,react是單向數(shù)據(jù)流。單向數(shù)據(jù)流的情況下,組件之間數(shù)據(jù)如何通信?組件的公共數(shù)據(jù)應(yīng)該放在哪里?


      redux.png
  • redux基本架構(gòu)圖

0_cntBtPADjE2ykLSP.png
  • dispatch函數(shù)

redux-diagram.jpg

2. 如何編寫redux中間件

  • 中間件函數(shù)本質(zhì)就是對dispatch方法的擴展,那么如何優(yōu)雅的擴展dispatch方法?
  • mid1,mid2,mid3分別為三個中間件函數(shù),編寫中間件函數(shù)有一個固定格式,必須按照以下格式編寫
// getState獲取當前state的狀態(tài)
function mid1({ getState }) {
// next指向下一個要執(zhí)行的(action) => {}匿名函數(shù)
  return (next) => {
  // action是指dispatch中的對象
    return (action) => {
      console.log('start mid1')
      next(action)
      console.log('end mid1');
    }
  }
}
// getState獲取當前state的狀態(tài)
function mid2({ getState }) {
// next指向下一個要執(zhí)行的(action) => {}匿名函數(shù)
  return (next) => {
  // action是指dispatch中的對象
    return (action) => {
      console.log('start mid2')
      next(action)
      console.log('end mid2');
    }
  }
}
// getState獲取當前state的狀態(tài)
function mid3({ getState }) {
// next指向下一個要執(zhí)行的(action) => {}匿名函數(shù)
  return (next) => {
    // action是指dispatch中的對象
    return (action) => {
      console.log('start mid3')
      next(action)
      console.log('getState() :', getState());
      console.log('end mid3');
    }
  }
}
// 配置中間件
const middleware = [mid1, mid2, mid3]
// 創(chuàng)建store
const finalCreateStore = applyMiddleware(...middleware)(createStore)
  • 觸發(fā)一次dispatch后的執(zhí)行結(jié)果


    WechatIMG95log.jpeg
  • 中間件洋蔥模型

  • 當用戶調(diào)用dispatch時,首先執(zhí)行mid1中間件,在mid1中調(diào)用next執(zhí)行mid2中間件,依次執(zhí)行,最終調(diào)用dispatch,dispatch調(diào)用結(jié)束后,依次執(zhí)行剩余中間件代碼。


    zIjmUzn.png

3. redux中間件源碼解析

// 配置中間件
const middleware = [mid1, mid2, mid3]
// 創(chuàng)建store
const finalCreateStore = applyMiddleware(...middleware)(createStore)
  • applyMiddleware函數(shù)

function applyMiddleware(...middlewares) {
// createStore創(chuàng)建store調(diào)用的方法
return createStore => (...args) => {
  const store = createStore(...args)
  const chain = middlewares.map(middleware => middleware())
  /*
    chain: [
      f1: (next) => (action) => { console.log('start mid1'); next(action); console.log('end mid1'); },
      f2: (next) => (action) => { console.log('start mid2'); next(action); console.log('end mid2'); },
      f3: (next) => (action) => { console.log('start mid3'); next(action); console.log('end mid3'); }
    ]
  */
  dispatch = compose(...chain)(store.dispatch)
  /*
    dispatch = f1(f2(f3(store.dispatch)))
  */
  return {
    ...store,
    dispatch
  }
}
}
  • compose

//  (f1, f2, f3) -> (...args) => f1(f2(f3(...args)))
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)))
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容