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

資訊專欄INFORMATION COLUMN

redux源碼分析之一:createStore.js

NotFound / 3519人閱讀

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

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

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

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

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

preloadedState:初始state

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

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

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

四、定義了幾個(gè)函數(shù):
//確保nextListeners和currentListeners不是同一個(gè)引用
function ensureCanMutateNextListeners() {
  if (nextListeners === currentListeners) {
    //如果是同一個(gè)引用,則淺拷貝currentListeners到nextListeners
    nextListeners = currentListeners.slice()
  }
}
//getState函數(shù),返回局部變量currentState,以獲取當(dāng)前狀態(tài)
function getState() {
  return currentState
}
  //注冊一個(gè)函數(shù),將注冊函數(shù)放入局部變量nextListeners數(shù)組里面
  //注冊函數(shù)的返回值是一個(gè)注銷函數(shù),注銷函數(shù)執(zhí)行可以將剛剛添加進(jìn)nextListeners的listener函數(shù)又刪除掉。這里很有意思,外部必須在調(diào)用subscribe執(zhí)行現(xiàn)場保存好unsubscribe函數(shù),否則將無法注銷一個(gè)函數(shù)
  function subscribe(listener) {
    //如果listener不是函數(shù),直接報(bào)錯(cuò)
    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)

    //返回一個(gè)函數(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ā)一個(gè)action,currentListeners中的所有函數(shù)都要執(zhí)行一遍
  function dispatch(action) {
    //如果action不是普通的對象,直接報(bào)錯(cuò)
    if (!isPlainObject(action)) {
      throw new Error(
        "Actions must be plain objects. " +
        "Use custom middleware for async actions."
      )
    }
    //如果action沒有type屬性,直接報(bào)錯(cuò):說明action對象必須要包含type字段
    if (typeof action.type === "undefined") {
      throw new Error(
        "Actions may not have an undefined "type" property. " +
        "Have you misspelled a constant?"
      )
    }
    //如果當(dāng)前正在觸發(fā)另外一個(gè)action,直接報(bào)錯(cuò)
    if (isDispatching) {
      throw new Error("Reducers may not dispatch actions.")
    }

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

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

    //該dispatch函數(shù)的返回值是原來的action
    return action
  }
  //替換reducer函數(shù):這個(gè)函數(shù)允許運(yùn)行時(shí)動(dòng)態(tài)替換最開始調(diào)用createStore函數(shù)時(shí)傳入的reducer,并且替換掉reducer之后,重新dispatch一個(gè)action,得到全新的currentState對象
  function replaceReducer(nextReducer) {
    //如果nextReducer不是函數(shù),直接報(bào)錯(cuò)
    if (typeof nextReducer !== "function") {
      throw new Error("Expected the nextReducer to be a function.")
    }
    //把新的reducer賦值給當(dāng)前的currentReducer變量,得到一個(gè)全新的currentReducer
    currentReducer = nextReducer
    // 觸發(fā)一個(gè)初始action:
    // 1.這樣就可以完成一次監(jiān)聽函數(shù)列表的全部調(diào)用
    // 2.可以得到一個(gè)全新的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
      }
    }
  }
五、初始化:

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

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

總結(jié)一下就是:

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

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

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

(完)

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

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

相關(guān)文章

  • Redux 莞式教程 之 進(jìn)階篇

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

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

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

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

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

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

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

    CloudwiseAPM 評論0 收藏0
  • Redux 入坑進(jìn)階 - 源碼解析

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

    BothEyes1993 評論0 收藏0

發(fā)表評論

0條評論

閱讀需要支付1元查看
<