成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

redux 核心源碼解析

cgh1999520 / 1588人閱讀

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

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

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

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

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

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

三大原則

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

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

使用純函數(shù)來(lái)執(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ù),就是下文將會(huì)介紹的 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 是只讀的:這個(gè) state 是 createStore 函數(shù)內(nèi)部變量,只能通過(guò) createStore 提供的 getState 方法讀取 state。
     */
    function getState() {
      return currentState
    }
    
    /**
     * listener 是函數(shù),維護(hù)在內(nèi)部變量 nextListeners(數(shù)組) 中
     * 調(diào)用 subscribe(訂閱) 方法,添加 listener 在數(shù)組中
     * 并返回一個(gè)方法,可以把當(dāng)前添加在數(shù)組中的 listener 函數(shù)取出。
     * 
     * listener 的作用:當(dāng) state 發(fā)生變化的時(shí)候,listener具體去做些事情,比如更新 UI。
     * 只定義做事情的時(shí)機(jī),具體做什么由調(diào)用者自己實(shí)現(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)生一個(gè)新的 state。
     * 
     * action的要求:是一個(gè)純粹的對(duì)象字面量,并且具有 type 字段
     * 經(jīng)過(guò) reducer 根據(jù) action 把 當(dāng)前 state 更新。一旦更新結(jié)束,立即把數(shù)組中的每一個(gè) 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 更新,把注冊(cè)的 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 更新,把注冊(cè)的 listener 執(zhí)行一遍
     */
    dispatch({ type: ActionTypes.INIT })
  
    return {
      dispatch,
      subscribe,
      getState,
      replaceReducer,
    }
  }
redux 中的中間件
redux 中的中間件一個(gè)典型的應(yīng)用場(chǎng)景是處理異步接口返回?cái)?shù)據(jù)

常見(jiàn)的 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;`;
    };

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

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

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

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

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

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/92645.html

相關(guān)文章

  • redux源碼解析

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

    crossea 評(píng)論0 收藏0
  • redux源碼解讀--compose源碼解析

    摘要:源碼解析模塊的代碼十分簡(jiǎn)練,但是實(shí)現(xiàn)的作用卻是十分強(qiáng)大。只傳遞一個(gè)參數(shù)的時(shí)候,就直接把這個(gè)函數(shù)返回返回組合函數(shù)這就是對(duì)源碼的一個(gè)整體解讀,水平有限,歡迎拍磚。后續(xù)的源碼解讀和測(cè)試?yán)涌梢躁P(guān)注源碼解讀倉(cāng)庫(kù) compose源碼解析 compose模塊的代碼十分簡(jiǎn)練,但是實(shí)現(xiàn)的作用卻是十分強(qiáng)大。redux為何稱為redux?有人說(shuō)就是reduce和flux的結(jié)合體,而reduce正是comp...

    lk20150415 評(píng)論0 收藏0
  • redux源碼解讀--createStore源碼解析

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

    tianren124 評(píng)論0 收藏0
  • 簡(jiǎn)單梳理Redux源碼與運(yùn)行機(jī)制

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

    betacat 評(píng)論0 收藏0
  • 簡(jiǎn)單梳理Redux源碼與運(yùn)行機(jī)制

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

    劉東 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<