成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

redux源碼分析之一:createStore.js

NotFound / 3459人閱讀

摘要:定義了幾個函數(shù)用于修改上面的幾個局部變量主要包括函數(shù)用于獲取用于替換用于修改列表用于觸發(fā)執(zhí)行,生成新的,并且,執(zhí)行列表中的每一個函數(shù)完整解析請參考我的,如果對您有幫助,歡迎,有任何問題也請指正。

歡迎關注redux源碼分析系列文章:
redux源碼分析之一:createStore.js
redux源碼分析之二:combineReducers.js
redux源碼分析之三:bindActionCreators.js
redux源碼分析之四:compose.js
redux源碼分析之五:applyMiddleware

createStore.js是redux的核心文件,暴露了一個函數(shù)createStore,函數(shù)執(zhí)行后返回一個對象,該對象包含了4個關鍵的方法:dispatch, subscribe, getState, replaceReducer,代碼如下。

export default function createStore(reducer, preloadedState, enhancer) {
    //中間代碼略
    return {
        dispatch,
        subscribe,
        getState,
        replaceReducer,
        [$$observable]: observable
      }
}
一、createStore函數(shù)的參數(shù):

reducer:reducer是一個函數(shù),該函數(shù)會返回一個全新的state,而state則保存了所有的數(shù)據

preloadedState:初始state

enhancer:這個參數(shù)特別有意思,如果該enhancer參數(shù)存在的話,會將當前的createStore函數(shù)作為參數(shù)傳入enhancer函數(shù),并且,enhancer執(zhí)行之后得到一個新函數(shù),該新函數(shù)其實就是一個加強版的createStore函數(shù),新的函數(shù)會把之前的reducer和preloadeState作為參數(shù)傳入并執(zhí)行。這個enhancer參數(shù)為redux中間件提供了入口。

二、參數(shù)檢查代碼及異常處理:
//如果preloadedState沒有傳,但是enhancer參數(shù)傳了,重置一下變量
if (typeof preloadedState === "function" && typeof enhancer === "undefined")          
  {
    enhancer = preloadedState
    preloadedState = undefined
  }
//如果enhancer傳了,但是不是函數(shù),則報錯提示,否則執(zhí)行enhancer函數(shù),
//并繼續(xù)執(zhí)行enhancer函數(shù)返回的加強版的createStore函數(shù),
//參數(shù)reducer以及preloadeState和原createStore函數(shù)保持一致
if (typeof enhancer !== "undefined") {
    if (typeof enhancer !== "function") {
      throw new Error("Expected the enhancer to be a function.")
    }
    return enhancer(createStore)(reducer, preloadedState)
  }
//如果reducer不是函數(shù),則報錯
if (typeof reducer !== "function") {
    throw new Error("Expected the reducer to be a function.")
}
三、定義的幾個局部變量:
let currentReducer = reducer //保存了當前的reducer函數(shù),該reducer函數(shù)可以被動態(tài)替換掉
let currentState = preloadedState //保存了當前的state數(shù)據
let currentListeners = [] //保存了當前注冊的函數(shù)列表
let nextListeners = currentListeners
let isDispatching = false  //是否正在dispatch一個action

最關鍵的是currentState變量,調用createStore之后,currentState變量保存了當前狀態(tài)的所有數(shù)據

四、定義了幾個函數(shù):
//確保nextListeners和currentListeners不是同一個引用
function ensureCanMutateNextListeners() {
  if (nextListeners === currentListeners) {
    //如果是同一個引用,則淺拷貝currentListeners到nextListeners
    nextListeners = currentListeners.slice()
  }
}
//getState函數(shù),返回局部變量currentState,以獲取當前狀態(tài)
function getState() {
  return currentState
}
  //注冊一個函數(shù),將注冊函數(shù)放入局部變量nextListeners數(shù)組里面
  //注冊函數(shù)的返回值是一個注銷函數(shù),注銷函數(shù)執(zhí)行可以將剛剛添加進nextListeners的listener函數(shù)又刪除掉。這里很有意思,外部必須在調用subscribe執(zhí)行現(xiàn)場保存好unsubscribe函數(shù),否則將無法注銷一個函數(shù)
  function subscribe(listener) {
    //如果listener不是函數(shù),直接報錯
    if (typeof listener !== "function") {
      throw new Error("Expected listener to be a function.")
    }

    let isSubscribed = true
    //確保nextListeners不是currentListeners,以保證修改的是nextListeners,而不是currentListeners
    ensureCanMutateNextListeners()
    //將監(jiān)聽函數(shù)放入監(jiān)聽函數(shù)列表尾部
    nextListeners.push(listener)

    //返回一個函數(shù),該函數(shù)可以從監(jiān)聽函數(shù)列表中刪除剛剛注冊的監(jiān)聽函數(shù)
    return function unsubscribe() {
      if (!isSubscribed) {
        return
      }

      isSubscribed = false

      ensureCanMutateNextListeners()
      const index = nextListeners.indexOf(listener)
      nextListeners.splice(index, 1)
    }
  }
  //觸發(fā)action的函數(shù):每次觸發(fā)一個action,currentListeners中的所有函數(shù)都要執(zhí)行一遍
  function dispatch(action) {
    //如果action不是普通的對象,直接報錯
    if (!isPlainObject(action)) {
      throw new Error(
        "Actions must be plain objects. " +
        "Use custom middleware for async actions."
      )
    }
    //如果action沒有type屬性,直接報錯:說明action對象必須要包含type字段
    if (typeof action.type === "undefined") {
      throw new Error(
        "Actions may not have an undefined "type" property. " +
        "Have you misspelled a constant?"
      )
    }
    //如果當前正在觸發(fā)另外一個action,直接報錯
    if (isDispatching) {
      throw new Error("Reducers may not dispatch actions.")
    }

    try {
      //先將標志位置為true
      isDispatching = true
      //執(zhí)行傳入的reducer函數(shù),該函數(shù)返回一個新的state對象,并賦值給currentState變量
      currentState = currentReducer(currentState, action)
    } finally {
      //reducer函數(shù)執(zhí)行完成后,將isDispatching恢復成false,方便下次action的觸發(fā)
      isDispatching = false
    }

    //每一次觸發(fā)一個action,所有的監(jiān)聽函數(shù)都要全部重新執(zhí)行一遍,
    //并且把上次得到的新的監(jiān)聽函數(shù)列表賦值成為當前的監(jiān)聽函數(shù)列表。這是一個懶操作,并不是在subscribe的時候就操作了,而是在dispatch的時候才操作
    const listeners = currentListeners = nextListeners
    for (let i = 0; i < listeners.length; i++) {
      const listener = listeners[i]
      listener()
    }

    //該dispatch函數(shù)的返回值是原來的action
    return action
  }
  //替換reducer函數(shù):這個函數(shù)允許運行時動態(tài)替換最開始調用createStore函數(shù)時傳入的reducer,并且替換掉reducer之后,重新dispatch一個action,得到全新的currentState對象
  function replaceReducer(nextReducer) {
    //如果nextReducer不是函數(shù),直接報錯
    if (typeof nextReducer !== "function") {
      throw new Error("Expected the nextReducer to be a function.")
    }
    //把新的reducer賦值給當前的currentReducer變量,得到一個全新的currentReducer
    currentReducer = nextReducer
    // 觸發(fā)一個初始action:
    // 1.這樣就可以完成一次監(jiān)聽函數(shù)列表的全部調用
    // 2.可以得到一個全新的currentState;
    dispatch({type: ActionTypes.INIT})
  }
function observable() {
    const outerSubscribe = subscribe
    return {
      /**
       * The minimal observable subscription method.
       * @param {Object} observer Any object that can be used as an observer.
       * The observer object should have a `next` method.
       * @returns {subscription} An object with an `unsubscribe` method that can
       * be used to unsubscribe the observable from the store, and prevent further
       * emission of values from the observable.
       */
      subscribe(observer) {
        if (typeof observer !== "object") {
          throw new TypeError("Expected the observer to be an object.")
        }

        function observeState() {
          if (observer.next) {
            observer.next(getState())
          }
        }

        observeState()
        const unsubscribe = outerSubscribe(observeState)
        return {unsubscribe}
      },

      [$$observable]() {
        return this
      }
    }
  }
五、初始化:

初始化很簡單,一句代碼,直接調用一次dispatch,就會執(zhí)行所有的注冊函數(shù),并且執(zhí)行reducer函數(shù),生成初始化的state

//馬上內部調用一次初始化的操作,根據傳入的reducer函數(shù),preloadedState生成一個全新的currentState和全新的reducer
  dispatch({type: ActionTypes.INIT})

總結一下就是:

createStore函數(shù)定義了幾個局部變量用于記錄狀態(tài),主要包括currentState記錄數(shù)據狀態(tài),currentListeners記錄注冊函數(shù)列表,currentReducer記錄當前的reducer函數(shù)。

定義了幾個函數(shù)用于修改上面的幾個局部變量:主要包括getState函數(shù)用于獲取currentState;replaceReducer用于替換currentReducer;subscribe用于修改currentListeners列表;dispatch用于觸發(fā)currentReducer執(zhí)行,生成新的currentState,并且,執(zhí)行currentListeners列表中的每一個函數(shù);

完整解析請參考我的github:https://github.com/abczhijia/...,如果對您有幫助,歡迎star,有任何問題也請指正。

(完)

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

轉載請注明本文地址:http://systransis.cn/yun/88897.html

相關文章

  • Redux 莞式教程 之 進階篇

    摘要:進階教程原文保持更新寫在前面相信您已經看過簡明教程,本教程是簡明教程的實戰(zhàn)化版本,伴隨源碼分析用的是編寫,看到有疑惑的地方的,可以復制粘貼到這里在線編譯總覽在的源碼目錄,我們可以看到如下文件結構打醬油的,負責在控制臺顯示警告信息入口文件除去 Redux 進階教程 原文(保持更新):https://github.com/kenberkele... 寫在前面 相信您已經看過 Redux ...

    岳光 評論0 收藏0
  • 解密Redux: 從源碼開始

    摘要:接下來筆者就從源碼中探尋是如何實現(xiàn)的。其實很簡單,可以簡單理解為一個約束了特定規(guī)則并且包括了一些特殊概念的的發(fā)布訂閱器。新舊中存在的任何都將收到先前的狀態(tài)。這有效地使用來自舊狀態(tài)樹的任何相關數(shù)據填充新狀態(tài)樹。 Redux是當今比較流行的狀態(tài)管理庫,它不依賴于任何的框架,并且配合著react-redux的使用,Redux在很多公司的React項目中起到了舉足輕重的作用。接下來筆者就從源碼...

    remcarpediem 評論0 收藏0
  • 史上最全的 Redux 源碼分析

    摘要:訂閱器不應該關注所有的變化,在訂閱器被調用之前,往往由于嵌套的導致發(fā)生多次的改變,我們應該保證所有的監(jiān)聽都注冊在之前。 前言 用 React + Redux 已經一段時間了,記得剛開始用Redux 的時候感覺非常繞,總搞不起里面的關系,如果大家用一段時間Redux又看了它的源碼話,對你的理解會有很大的幫助。看完后,在回來看Redux,有一種 柳暗花明又一村 的感覺 ,. 源碼 我分析的...

    fai1017 評論0 收藏0
  • 我的源碼閱讀之路:redux源碼剖析

    摘要:到月底了,小明的爸爸的單位發(fā)了工資總計塊大洋,拿到工資之后第一件的事情就是上交,毫無疑問的,除非小明爸爸不要命了。當小明的爸爸收到這個通知之后,心的一塊大石頭也就放下來了。下面我們正式開始我們的源碼閱讀之旅。 前言 用過react的小伙伴對redux其實并不陌生,基本大多數(shù)的React應用用到它。一般大家用redux的時候基本都不會單獨去使用它,而是配合react-redux一起去使用...

    CloudwiseAPM 評論0 收藏0
  • Redux 入坑進階 - 源碼解析

    摘要:否則的話,認為只是一個普通的,將通過也就是進一步分發(fā)。在本組件內的應用傳遞給子組件源碼解析期待一個作為傳入,里面是如果只是傳入一個,則通過返回被綁定到的函數(shù)遍歷并通過分發(fā)綁定至將其聲明為的屬性之一接收的作為傳入。 原文鏈接:https://github.com/ecmadao/Co...轉載請注明出處 本文不涉及redux的使用方法,因此可能更適合使用過redux的玩家翻閱? 預熱...

    BothEyes1993 評論0 收藏0

發(fā)表評論

0條評論

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