国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

redux 核心源碼解析

cgh1999520 / 1537人閱讀

摘要:核心源碼解析本文默認,你已經(jīng)有了一定的基礎(chǔ)。定義如何更新初始狀態(tài)是讓中間件按照規(guī)定模型洋蔥模型回形針模型執(zhí)行的函數(shù),就是下文將會介紹的函數(shù)的返回值返回中的。洋蔥模型回形針模型調(diào)用后的結(jié)果對上面的代碼換一種展現(xiàn)方式中間件要執(zhí)行,先得執(zhí)行。

redux 核心源碼解析
本文默認,你已經(jīng)有了一定的es6基礎(chǔ)。源碼有刪減,對其中的核心邏輯做解釋

redux 是 一個用 javascript 管理數(shù)據(jù)的容器,這個容器的狀態(tài)是可以預(yù)測的。

redux 可以跟任何是個 視圖(view)層的框架結(jié)合使用

開發(fā)react應(yīng)用,經(jīng)常結(jié)合使用 redux

redux 比較抽象,核心旨在定義一個數(shù)據(jù)讀寫的規(guī)范,和數(shù)據(jù)變化后的回調(diào)接口

三大原則

單一數(shù)據(jù)源 :整個應(yīng)用的 state 被儲存在一棵 object tree 中,并且這個 object tree 只存在于唯一一個 store 中。

State 是只讀的:惟一改變 state 的方法就是觸發(fā) action,action 是一個用于描述已發(fā)生事件的普通對象。

使用純函數(shù)來執(zhí)行修改 :為了描述 action 如何改變 state tree ,你需要編寫 reducers。純函數(shù):http://web.jobbole.com/86136/

createStore.js 核心邏輯
function createStore(reducer, preloadedState, enhancer) {
    /*
      參數(shù)格式/類型 匹配。
      reducer:定義 state 如何更新
      preloadedState: 初始狀態(tài)
      enhancer 是讓中間件按照規(guī)定模型(洋蔥模型/回形針模型)執(zhí)行的函數(shù),就是下文將會介紹的 applyMiddleware函數(shù)的返回值
    */
    if (typeof preloadedState === "function" && typeof enhancer === "undefined") {
      enhancer = preloadedState
      preloadedState = undefined
    }
    if (typeof enhancer !== "undefined") {
      if (typeof enhancer !== "function") {
        throw new Error("Expected the enhancer to be a function.")
      }
      return enhancer(createStore)(reducer, preloadedState)
    }
  
    let currentReducer = reducer
    let currentState = preloadedState
    let currentListeners = []
    let nextListeners = currentListeners
  
    /**
     *  返回 store 中的 state。
     *  State 是只讀的:這個 state 是 createStore 函數(shù)內(nèi)部變量,只能通過 createStore 提供的 getState 方法讀取 state。
     */
    function getState() {
      return currentState
    }
    
    /**
     * listener 是函數(shù),維護在內(nèi)部變量 nextListeners(數(shù)組) 中
     * 調(diào)用 subscribe(訂閱) 方法,添加 listener 在數(shù)組中
     * 并返回一個方法,可以把當前添加在數(shù)組中的 listener 函數(shù)取出。
     * 
     * listener 的作用:當 state 發(fā)生變化的時候,listener具體去做些事情,比如更新 UI。
     * 只定義做事情的時機,具體做什么由調(diào)用者自己實現(xiàn)
     */
    function subscribe(listener) {
      nextListeners.push(listener)
      return function unsubscribe() {
        const index = nextListeners.indexOf(listener)
        nextListeners.splice(index, 1)
      }
    }
    
    /**
     * dispatch的作用:更改 state
     * 更改的方式:根據(jù)傳入的 reducer 和 action,產(chǎn)生一個新的 state。
     * 
     * action的要求:是一個純粹的對象字面量,并且具有 type 字段
     * 經(jīng)過 reducer 根據(jù) action 把 當前 state 更新。一旦更新結(jié)束,立即把數(shù)組中的每一個 listener 調(diào)用一遍
    */
    function dispatch(action) {
      if (!isPlainObject(action)) {
        throw new Error(
          "Actions must be plain objects. " +
            "Use custom middleware for async actions."
        )
      }
  
      if (typeof action.type === "undefined") {
        throw new Error(
          "Actions may not have an undefined "type" property. " +
            "Have you misspelled a constant?"
        )
      }
  
      currentState = currentReducer(currentState, action)
  
      const listeners = (currentListeners = nextListeners)
      for (let i = 0; i < listeners.length; i++) {
        const listener = listeners[i]
        listener()
      }
  
      return action
    }
  
    /**
     * 可以更改 reducer 
     * reducer 一旦更改,立即 dispatch 一次,把 state 更新,把注冊的 listener 執(zhí)行一遍
     */
    function replaceReducer(nextReducer) {
      if (typeof nextReducer !== "function") {
        throw new Error("Expected the nextReducer to be a function.")
      }
  
      currentReducer = nextReducer
      dispatch({ type: ActionTypes.REPLACE })
    }
  
    /**
     * 一旦 調(diào)用 createStore 函數(shù),立即 dispatch 一遍,把 state 更新,把注冊的 listener 執(zhí)行一遍
     */
    dispatch({ type: ActionTypes.INIT })
  
    return {
      dispatch,
      subscribe,
      getState,
      replaceReducer,
    }
  }
redux 中的中間件
redux 中的中間件一個典型的應(yīng)用場景是處理異步接口返回數(shù)據(jù)

常見的 web 系統(tǒng)中的中間件,不侵入業(yè)務(wù)邏輯,功能優(yōu)盤化,即用即插。

洋蔥模型/回形針模型
    middleWareA(middleWareB(middleWareC("hello world")));
    /**
     * 調(diào)用后的結(jié)果: 
     * hello world form middleWareC;form middleWareB;form middleWareA;
     * */ 

    function middleWareA(string){
        return `${string} form middleWareA;`;
    };
    function middleWareB(string){
        return `${string} form middleWareB;`;
    };
    function middleWareC(string){
        return `${string} form middleWareC;`;
    };

對上面的代碼換一種展現(xiàn)方式

    middleWareA(
        middleWareB(
            middleWareC("hello world")
        )
    );

中間件 middleWareA 要執(zhí)行,先得執(zhí)行 middleWareB。中間件 middleWareB 要執(zhí)行,先得執(zhí)行 middleWareC,數(shù)據(jù)層層傳遞
調(diào)用順序為: A-->B-->C
執(zhí)行結(jié)束的順序為:C-->B-->A
這就是 洋蔥模型 或者 回形針模型
下面看一個 redux-thunk 中間件

redux-thunk 核心邏輯
function createThunkMiddleware() {
  /**
   * dispatch 是基于 store.dispatch,且層層經(jīng)過中間件包裝后的方法
   * getState 是 createStore 函數(shù)執(zhí)行后導(dǎo)出的方法;
   * next 為下一個中間件
   * action 的預(yù)期格式為 createStore 中設(shè)計的 action的格式,是一個字面量對象。在這里做action類型的判斷
  */
  return ({ dispatch, getState }) => next => action => {
    // 如果 action 是函數(shù)
    if (typeof action === "function") {
        return action(dispatch, getState);
    }
    // 如果不是函數(shù),流轉(zhuǎn)到下一個中間件,期待最后的一個中間件的 action 是一個預(yù)期模式的 action
    return next(action);
  };
}

export default createThunkMiddleware();
applyMiddleware 核心邏輯
/**
 * middlewares 是包含中間件的數(shù)組
 * 需要的中間件,依次傳入。如: applyMiddleware(middlewaresA, middlewaresB, middlewaresC)
 * applyMiddleware 執(zhí)行后的返回的函數(shù)就是一個 enhancer
*/
export default function applyMiddleware(...middlewares) {
    return createStore => (...args) => {
      // args解構(gòu)后,就是 reducer, preloadedState
      // 這里的 store 就是 createStore 函數(shù)生產(chǎn)的全局的狀態(tài)樹,參見上文對 createStore 的解釋
      const store = createStore(...args)
  
      let dispatch = () => { };
      let chain = []
  
      /**
       * 每個中間件中需要傳遞的數(shù)據(jù)
       */
      const middlewareAPI = {
        getState: store.getState,// 獲取 state 的函數(shù),用于讀
        dispatch: (...args) => dispatch(...args)// 更新 state 的函數(shù),用于寫。
      }
      // 遍歷中間件
      chain = middlewares.map(middleware => middleware(middlewareAPI))
      
      // 下面的代碼的效果,就是要運用洋蔥模型/回形針模型:middlewareA(middlewareB(middlewareC(store.dispatch)))
      // 關(guān)于 compose 比較簡單:https://github.com/reactjs/redux/blob/master/src/compose.js
      // 中間件的開始是 原生的store.dispatch,結(jié)束時是 一個攜帶了各種中間件信息的 dispatch
      dispatch = compose(...chain)(store.dispatch)
  
      /**
       * 尤其注意這里的 dispatch
       * 開始時定義了一個空的 dispatch 函數(shù),是為了給 middlewareAPI 的 dispatch 一個初始值
       * 實際上真正的 dispatch 是中間件根據(jù)原生的 store.dispatch 按照洋蔥模型/回形針模型,執(zhí)行了一邊,調(diào)用所有中間件后的 dispatch
       * 這個 dispatch 攜帶了傳入的每一個中間件的操作。一次如果此時傳入 action 更新 state,所有的中間件都會被執(zhí)行一遍。
      */
  
      return {
        ...store,
        dispatch
      }
    }
  }

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/92645.html

相關(guān)文章

  • redux源碼解析

    摘要:此篇文章可作為源碼導(dǎo)讀使用,只說明了其中部分核心代碼,并進行了一些簡化處理用法回顧用來創(chuàng)建創(chuàng)建在中編寫純函數(shù)來處理用通過和來操作里的數(shù)據(jù)用來監(jiān)聽中的數(shù)據(jù)是否發(fā)生了變化用來獲取中的,并更新視圖核心代碼初始化數(shù)據(jù)存放,是傳入的默認值存放傳入的創(chuàng) 此篇文章可作為redux源碼導(dǎo)讀使用,只說明了其中部分核心代碼,并進行了一些簡化處理 用法回顧 用createStore來創(chuàng)建store 創(chuàng)建A...

    crossea 評論0 收藏0
  • redux源碼解讀--compose源碼解析

    摘要:源碼解析模塊的代碼十分簡練,但是實現(xiàn)的作用卻是十分強大。只傳遞一個參數(shù)的時候,就直接把這個函數(shù)返回返回組合函數(shù)這就是對源碼的一個整體解讀,水平有限,歡迎拍磚。后續(xù)的源碼解讀和測試例子可以關(guān)注源碼解讀倉庫 compose源碼解析 compose模塊的代碼十分簡練,但是實現(xiàn)的作用卻是十分強大。redux為何稱為redux?有人說就是reduce和flux的結(jié)合體,而reduce正是comp...

    lk20150415 評論0 收藏0
  • redux源碼解讀--createStore源碼解析

    摘要:源碼解析是最核心的模塊。比如,當我們需要使用中間件的時候,就會像第三個參數(shù)傳遞一個返回值是一個。后續(xù)的源碼解讀和測試例子可以關(guān)注源碼解讀倉庫 createStore源碼解析 createStore是redux最核心的模塊。這個模塊就是用于創(chuàng)建一個store對象,同時,對外暴露出dispatch,getState,subscribe和replaceReducer方法。(源碼中關(guān)于obse...

    tianren124 評論0 收藏0
  • 簡單梳理Redux源碼與運行機制

    摘要:然后循環(huán)調(diào)用中的更新函數(shù),更新函數(shù)一般是我們的渲染函數(shù),函數(shù)內(nèi)部會調(diào)用來獲取數(shù)據(jù),所以頁面會更新。 歡迎訪問個人網(wǎng)站:https://www.neroht.com/ 前言 前幾天寫了一篇react另一個狀態(tài)管理工具Unstated的源碼解析。開啟了我的看源碼之路。想一想用了好長時間的redux,但從沒有深究過原理,遇到報錯更是懵逼,所以就啃了一遍它的源碼,寫了這篇文章,分享我對于它的理...

    betacat 評論0 收藏0
  • 簡單梳理Redux源碼與運行機制

    摘要:然后循環(huán)調(diào)用中的更新函數(shù),更新函數(shù)一般是我們的渲染函數(shù),函數(shù)內(nèi)部會調(diào)用來獲取數(shù)據(jù),所以頁面會更新。前言 前幾天寫了一篇react另一個狀態(tài)管理工具Unstated的源碼解析。 開啟了我的看源碼之路。想一想用了好長時間的redux,但從沒有深究過原理,遇到報錯更是懵逼,所以就啃了一遍它的源碼,寫了這篇文章, 分享我對于它的理解。 API概覽 看一下redux源碼的index.js,看到了我們最...

    劉東 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<