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

資訊專欄INFORMATION COLUMN

淺析Redux源碼

lifesimple / 870人閱讀

摘要:用法源碼由在年創建的科技術語。我們除去源碼校驗函數部分,從最終返回的大的來看。這個返回值無法被識別。洋蔥模型我們來看源碼源碼每個都以作為參數進行注入,返回一個新的鏈。改變原始組數,是一種副作用。

@(Redux)[|用法|源碼]

Redux 由Dan Abramov在2015年創建的科技術語。是受2014年Facebook的Flux架構以及函數式編程語言Elm啟發。很快,Redux因其簡單易學體積小短時間內成為最熱門的前端架構。

@[三大原則]

單一數據源 - 整個應用的state被儲存在一棵object tree中,并且這個object tree只存在于唯一一個store中。所有數據會通過store.getState()方法調用獲取.

State‘只讀’ - 根據State只讀原則,數據變更會通過store,dispatch(action)方法.

使用純函數修改 -Reducer只是一些純函數1,它接收先前的stateaction,并返回新的state.

[TOC]

準備階段 柯里化函數(curry)
    //curry example
    const A  = (a) => {
        return (b) => {
            return a + b
        }
    }

通俗的來講,可以用一句話概括柯里化函數:返回函數的函數.
優點: 避免了給一個函數傳入大量的參數,將參數的代入分離開,更有利于調試。降低耦合度和代碼冗余,便于復用.

代碼組合(compose)

舉個例子

    let init = (...args) => args.reduce((ele1, ele2) => ele1 + ele2, 0)
    let step2 = (val) => val + 2
    let step3 = (val) => val + 3
    let step4 = (val) => val + 4
    let steps = [step4, step3, step2, init]
    let composeFunc = compose(...steps)
    console.log(composeFunc(1, 2, 3))
    // 1+2+3+2+3+4 = 15

接下來看下FP思想的compose的源碼

    const compose = function (...args) {
      let length = args.length
      let count = length - 1
      let result
      let this_ = this
      // 遞歸
      return function f1(...arg1) {
        result = args[count].apply(this, arg1)
        if (count <= 0) {
          count = length - 1
          return result
        }
        count--
        return f1.call(null, result)
      }
    }

通俗的講: 從右到左執行函數,最右函數以arguments為參數,其余函數以上個函數結果為入參數執行。

優點: 通過這樣函數之間的組合,可以大大增加可讀性,效果遠大于嵌套一大堆的函數調用,并且我們可以隨意更改函數的調用順序

CombineReducers 作用

隨著整個項目越來越大,state狀態樹也會越來越龐大,state的層級也會越來越深,由于redux只維護唯一的state,當某個action.type所對應的需要修改state.a.b.c.d.e.f時,我的函數寫起來就非常復雜,我必須在這個函數的頭部驗證state 對象有沒有那個屬性。這是讓開發者非常頭疼的一件事。于是有了CombineReducers。我們除去源碼校驗函數部分,從最終返回的大的Reducers來看。

Note:

FinalReducers : 通過=== "function"校驗后的Reducers.

FinalReducerKeys : FinalReducers的所有key

(與入參Objectkey區別:過濾了value不為function的值)

源碼
      // 返回一個function。該方法接收state和action作為參數
      return function combination(state = {}, action) {
        var hasChanged = false
        var nextState = {}
        // 遍歷所有的key和reducer,分別將reducer對應的key所代表的state,代入到reducer中進行函數調用
        for (var i = 0; i < finalReducerKeys.length; i++) {
          var key = finalReducerKeys[i]
          var reducer = finalReducers[key]
          // CombineReducers入參Object中的Value為reducer function,從這可以看出reducer function的name就是返回給store中的state的key。
          var previousStateForKey = state[key]
          // debugger
          var nextStateForKey = reducer(previousStateForKey, action)
          // 如果reducer返回undefined則拋出錯誤
          if (typeof nextStateForKey === "undefined") {
            var errorMessage = getUndefinedStateErrorMessage(key, action)
            throw new Error(errorMessage)
          }
          // 將reducer返回的值填入nextState
          nextState[key] = nextStateForKey
          // 如果任一state有更新則hasChanged為true
          hasChanged = hasChanged || nextStateForKey !== previousStateForKey
        }
        return hasChanged ? nextState : state
      }
小結

combineReducers實現方法很簡單,它遍歷傳入的reducers,返回一個新的reducer.該函數根據Statekey 去執行相應的子Reducer,并將返回結果合并成一個大的State 對象。

CreateStore 作用

createStore主要用于Store的生成,我們先整理看下createStore具體做了哪些事兒。(這里我們看簡化版代碼)

源碼(簡化版)
const createStore = (reducer, initialState) => {
      // initialState一般設置為null,或者由服務端給默認值。
      // internal variables
      const store = {};
      store.state = initialState;
      store.listeners = [];
      // api-subscribe
      store.subscribe = (listener) => {
        store.listeners.push(listener);
      };
      // api-dispatch
      store.dispatch = (action) => {
        store.state = reducer(store.state, action);
        store.listeners.forEach(listener => listener());
      };
      // api-getState
      store.getState = () => store.state;
      
      return store;
    }
小結

源碼角度,一大堆類型判斷先忽略,可以看到聲明了一系列函數,然后執行了dispatch方法,最后暴露了dispatchsubscribe……幾個方法。這里dispatch了一個init Action是為了生成初始的State樹。

ThunkMiddleware 作用

首先,說ThunkMiddleware之前,也許有人會問,到底middleware有什么用?
這就要從action說起。在redux里,action僅僅是攜帶了數據的普通js對象。action creator返回的值是這個action類型的對象。然后通過store.dispatch()進行分發……

action ---> dispatcher ---> reducers
同步的情況下一切都很完美……
如果遇到異步情況,比如點擊一個按鈕,希望1秒之后顯示。我們可能這么寫:

function (dispatch) {
        setTimeout(function () {
            dispatch({
                type: "show"
            })
        }, 1000)
    }

這會報錯,返回的不是一個action,而是一個function。這個返回值無法被reducer識別。

大家可能會想到,這時候需要在actionreducer之間架起一座橋梁……
當然這座橋梁就是middleware。接下來我們先看看最簡單,最精髓的ThunkMiddleware的源碼

源碼
const thunkMiddleware = ({ dispatch, getState }) => {
      return next => action => {
        typeof action === "function" ?
          action(dispatch, getState) :
          next(action)
      }
    }

非常之精髓。。。我們先記住上述代碼,引出下面的ApplyMiddleware

ApplyMiddleware 作用

介紹applyMiddleware之前我們先看下項目中store的使用方法如下:

  let step = [ReduxThunk, middleware, ReduxLogger]
  let store = applyMiddleware(...step)(createStore)(reducer)
  return store

通過使用方法可以看到有3處柯里化函數的調用,applyMiddleware 函數Redux 最精髓的地方,成功的讓Redux 有了極大的可拓展空間,在action 傳遞的過程中帶來無數的“副作用”,雖然這往往也是麻煩所在。 這個middleware的洋蔥模型思想是從koa的中間件拿過來的,用圖來表示最直觀。

洋蔥模型


我們來看源碼:

源碼
    const applyMiddleware = (...middlewares) => {
      return (createStore) => (reducer, initialState, enhancer) => {
        var store = createStore(reducer, initialState, enhancer)
        var dispatch
        var chain = []
        var middlewareAPI = {
          getState: store.getState,
          dispatch: (action) => dispatch(action)
        }
        // 每個 middleware 都以 middlewareAPI 作為參數進行注入,返回一個新的鏈。
        // 此時的返回值相當于調用 thunkMiddleware 返回的函數: (next) => (action) => {} ,接收一個next作為其參數
        chain = middlewares.map(middleware => middleware(middlewareAPI))
        // 并將鏈代入進 compose 組成一個函數的調用鏈
        dispatch = compose(...chain)(store.dispatch)
        return {
          ...store,
          dispatch
        }
      }
    }

applyMiddleware函數第一次調用的時候,返回一個以createStore為參數的匿名函數,這個函數返回另一個以reducer,initialState,enhancer為參數的匿名函數.我們在使用方法中,分別可以看到傳入的值。
結合一個簡單的實例來理解中間件以及洋蔥模型

    // 傳入middlewareA
    const middlewareA = ({ dispatch, getState }) => {
      return next => action => {
        console.warn("A middleware start")
        next(action)
        console.warn("A middleware end")
      }
    }
    // 傳入多個middlewareB
    const middlewareB = ({ dispatch, getState }) => {
      return next => action => {
        console.warn("B middleware start")
        next(action)
        console.warn("B middleware end")
      }
    }
    // 傳入多個middlewareC
    const middlewareC = ({ dispatch, getState }) => {
      return next => action => {
        console.warn("C middleware start")
        next(action)
        console.warn("C middleware end")
      }
    }

當我們傳入多個類似A,B,C的middlewareapplyMiddleware后,調用

dispatch = compose(...chain)(store.dispatch)

結合場景并且執行compose結果為:

dispatch = middlewareA(middlewareB(middlewareC(store.dispatch)))

從中我們可以清晰的看到middleware函數中的next函數相互連接,這里體現了compose FP編程思想中代碼組合的強大作用。再結合洋蔥模型的圖片,不難理解是怎么樣的一個工作流程。

最后我們看結果,當我們觸發一個store.dispath的時候進行分發。則會先進入middlewareA并且打印A start 然后進入next函數,也就是middlewareB同時打印B start,然后觸發next函數,這里的next函數就是middlewareC,然后打印C start,之后才處理dispath,處理完成后先打印C end,然后B end,最后A end。完成整體流程。

小結

Redux applyMiddleware機制的核心在于,函數式編程(FP)compose組合函數,需將所有的中間件串聯起來。

為了配合compose對單參函數的使用,對每個中間件采用currying的設計。同時,利用閉包原理做到每個中間件共享Store。(middlewareAPI的注入)

Feedback & Bug Report

github: @同性交友網站

Thank you for reading this record.

  • 純函數,它不依賴于外部環境(例如:全局變量、環境變量)、不改變外部環境(例如:發送請求、改變DOM結構),函數的輸出完全由函數的輸入決定。比如 slice 和 splice,這兩個函數的作用并無二致——但是注意,它們各自的方式卻大不同,但不管怎么說作用還是一樣的。我們說 slice 符合純函數的定義是因為對相同的輸入它保證能返回相同的輸出。而 splice 卻會嚼爛調用它的那個數組,然后再吐出來;這就會產生可觀察到的副作用,即這個數組永久地改變了。可以看到,splice改變了原始數組,而slice沒有。我們認為,slice不改變原來數組的方式更加“安全”。改變原始組數,是一種“副作用”。 ?

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

    轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/94974.html

    相關文章

    • 淺析`redux-thunk`中間件源碼

      摘要:大多的初學者都會使用中間件來處理異步請求,其理解簡單使用方便具體使用可參考官方文檔。源碼的源碼非常簡潔,出去空格一共只有行,這行中如果不算上則只有行。官方文檔中的一節講解的非常好,也確實幫我理解了中間件的工作原理,非常推薦閱讀。 總覺得文章也應該是有生命力的,歡迎關注我的Github上的博客,這里的文章會依據我本人的見識,逐步更新。 大多redux的初學者都會使用redux-thunk...

      wing324 評論0 收藏0
    • redux淺析

      摘要:概念是一個狀態管理容器使用可以更好的管理和監測組件之間需要通信的數據。參考源碼參考鏈接 redux概念 redux是一個狀態管理容器,使用redux可以更好的管理和監測組件之間需要通信的數據。 redux基本原則 單一數據源 在redux中,整個應用保持一個數據源,數據源是一個樹形的結構 狀態只讀 狀態只讀意思是不能直接修改,需要通過dispatch action方式才可以,返回的是一...

      galois 評論0 收藏0
    • react路由淺析

      摘要:瀏覽器端使用的和集成使用時會用到中路由分類基于提供的和事件來保持和的同步。路由剖析在上面的示例中是轉發的樞紐在這個中轉站有很多線路通過開關可以啟動列車的運行乘坐列車就可以發現新大陸。 引言 在使用react做復雜的spa開發中,開發中必不可少的就是react-router,它使用Lerna管理多個倉庫, 在browser端常使用的幾個如下所示 react-router 提供了路由的...

      jackzou 評論0 收藏0
    • 前端進階資源整理

      摘要:前端進階進階構建項目一配置最佳實踐狀態管理之痛點分析與改良開發中所謂狀態淺析從時間旅行的烏托邦,看狀態管理的設計誤區使用更好地處理數據愛彼迎房源詳情頁中的性能優化從零開始,在中構建時間旅行式調試用輕松管理復雜狀態如何把業務邏輯這個故事講好和 前端進階 webpack webpack進階構建項目(一) Webpack 4 配置最佳實踐 react Redux狀態管理之痛點、分析與...

      BlackMass 評論0 收藏0
    • 淺析Redux數據流

      摘要:原文地址數據流通過這張流程圖,我們可以更好的理解和直接數據如何流通,關系如何映射。函數只是一個純函數,它接收應用程序的當前狀態以及發生的,然后返回修改后的新狀態或者有人稱之為歸并后的狀態。的更新意味著更新。 原文地址:https://github.com/YutHelloWo... showImg(https://segmentfault.com/img/bVRQRK?w=1205&h...

      chaosx110 評論0 收藏0

    發表評論

    0條評論

    lifesimple

    |高級講師

    TA的文章

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