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

資訊專欄INFORMATION COLUMN

redux深入進(jìn)階

omgdog / 2410人閱讀

摘要:上一篇文章講解了如何使用,本篇文章將進(jìn)一步深入,從的源碼入手,深入學(xué)習(xí)的中間件機(jī)制。的功能是讓支持異步,讓我們可以在中跟服務(wù)器進(jìn)行交互等操作,而他的實(shí)現(xiàn)。。。

上一篇文章講解了redux如何使用,本篇文章將進(jìn)一步深入,從redux的源碼入手,深入學(xué)習(xí)redux的中間件機(jī)制。
在這里我們會(huì)以一個(gè)redux-thunk中間件為例,逐步分解redux的中間機(jī)制如何操作,如何執(zhí)行。

閑話不多說,上代碼。

如何加載中間件
import { createStore, applyMiddleware } from "redux";
import thunk from "redux-thunk";
import rootReducer from "./reducers/index";

// create a store that has redux-thunk middleware enabled
const createStoreWithMiddleware = applyMiddleware(
  thunk
)(createStore);

const store = createStoreWithMiddleware(rootReducer);

這里需要用到redux中提供的一個(gè)工具方法,叫做applyMiddleware,向該方法傳入你想要使用的中間件,完了之后再傳入createStore方法,
最終形成新的創(chuàng)建store的方法。

這顯然是一個(gè)裝飾器模式,通過不同的中間件對(duì)createStore方法進(jìn)行修飾,最后形成新的createStore方法,那么創(chuàng)建的store就具有這些中間件的特性,
非常出色的設(shè)計(jì),驚喜不僅在這,看了之后的代碼你就更不得不佩服作者的代碼設(shè)計(jì)能力。

瞬間覺得別人都是碼神,而我就是碼農(nóng)有木有/(ㄒoㄒ)/~~

中間件加載機(jī)制的實(shí)現(xiàn)

先來看applyMiddleware方法的實(shí)現(xiàn)

import compose from "./compose";

/**
 * Creates a store enhancer that applies middleware to the dispatch method
 * of the Redux store. This is handy for a variety of tasks, such as expressing
 * asynchronous actions in a concise manner, or logging every action payload.
 *
 * See `redux-thunk` package as an example of the Redux middleware.
 *
 * Because middleware is potentially asynchronous, this should be the first
 * store enhancer in the composition chain.
 *
 * Note that each middleware will be given the `dispatch` and `getState` functions
 * as named arguments.
 *
 * @param {...Function} middlewares The middleware chain to be applied.
 * @returns {Function} A store enhancer applying the middleware.
 */
export default function applyMiddleware(...middlewares) {
  return (next) => (reducer, initialState) => {
    var store = next(reducer, initialState);
    var dispatch = store.dispatch;
    var chain = [];

    var middlewareAPI = {
      getState: store.getState,
      dispatch: (action) => dispatch(action)
    };
    chain = middlewares.map(middleware => middleware(middlewareAPI));
    dispatch = compose(...chain)(store.dispatch);

    return {
      ...store,
      dispatch
    };
  };
}

這就是redux里面這個(gè)方法的源碼,其中還一半是注釋有木有。。。本來以為肯定有百來行代碼的
當(dāng)然這里不得不說es6的特性提供了非常多的幫助,所以為了省力吧es6玩透還是灰常有必要的(更別說為了裝X了(^__^) )

從這里開始代碼就有點(diǎn)繞了,我們逐行分析

return (next) => (reducer, initialState) => {...}

整個(gè)applyMiddleware方法就是返回了一個(gè)方法,根據(jù)applyMiddleware方法的使用,我們可以知道next就是createStore方法,
因?yàn)樽罱K我們要返回的是一個(gè)裝飾過的createStore方法,那么接收的參數(shù)肯定是不會(huì)變,所以最終我們調(diào)用createStoreWithMiddleware方法其實(shí)就是調(diào)用

function (reducer, initialState) {
    var store = next(reducer, initialState); // next即為最初的createStore方法
    // ...以下省略
}
var store = next(reducer, initialState);
var dispatch = store.dispatch;
var chain = [];

這里沒什么好講的,首先創(chuàng)建了一個(gè)store,這個(gè)store就是最原始的通過createStore創(chuàng)建的store,后兩行只是變量賦值

var middlewareAPI = {
  getState: store.getState,
  dispatch: (action) => dispatch(action)
};
chain = middlewares.map(middleware => middleware(middlewareAPI));
dispatch = compose(...chain)(store.dispatch);

這里是關(guān)鍵,必須詳細(xì)進(jìn)行講解。

首先,這邊聲明了一個(gè)middlewareAPI對(duì)象,這個(gè)對(duì)象包含兩個(gè)方法:

getState:store中的getState方法的引用

dispatch:對(duì)本身的dispatch方法進(jìn)行一次封裝

然后

chain = middlewares.map(middleware => middleware(middlewareAPI));

我們來仔細(xì)看看這行代碼,首先我們對(duì)所有的中間件進(jìn)行一個(gè)map,map結(jié)果就是調(diào)用中間件方法,將middlewareAPI作為參數(shù)傳入,
這里我們拿redux-thunk中間件舉例,來看看一個(gè)中間件是長(zhǎng)什么樣子的,傳入的參數(shù)又是用來干嘛的。

export default function thunkMiddleware({ dispatch, getState }) {
  return next => action =>
    typeof action === "function" ?
      action(dispatch, getState) :
      next(action);
}

redux-thunk的功能是讓action支持異步,讓我們可以在action中跟服務(wù)器進(jìn)行交互等操作,而他的實(shí)現(xiàn)。。。(⊙﹏⊙)b是的,又是這么幾行代碼。

我們回顧之前的代碼,在map所有中間件的時(shí)候我們調(diào)用了thunkMiddleware方法,傳入兩個(gè)方法dispatchgetState,然后返回了一個(gè)方法,
我們大致抽象一下,應(yīng)該如下:

function (next) {
  
  return function (action) {
    typeof action === "function" ?
      action(dispatch, getState) :
      next(action)
  }
  
}

于是我們接下去分析applyMiddleware里面的代碼,

chain = middlewares.map(middleware => middleware(middlewareAPI));

現(xiàn)在我們知道chain是一個(gè)數(shù)組,每一項(xiàng)是調(diào)用每個(gè)中間件之后的返回函數(shù)

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

compose是redux里面的一個(gè)幫助函數(shù),代碼如下:

export default function compose(...funcs) {
  return arg => funcs.reduceRight((composed, f) => f(composed), arg);
}

~~(>_<)~~我已經(jīng)不想再吐槽什么了,

我們看到這邊先調(diào)用了compose函數(shù),傳入了結(jié)構(gòu)后的chain數(shù)組,然后compose函數(shù)返回的也是一個(gè)函數(shù):

function (arg) {
  return funcs.reduceRight((composed, f) => f(composed), arg);
  // funcs就是中間件數(shù)組
}

然后我們把store.dispatch函數(shù)作為arg傳入這個(gè)結(jié)果,這里reduceRight可以參考這里
。那么這邊得到的結(jié)果是什么呢?

// 假設(shè)中間件數(shù)組是[A, B, C]
// 那么結(jié)果就是A(B(C(store.dispatch)))

再次結(jié)合redux-thunk來看,我們假設(shè)只有一個(gè)中間件,那么最終的dispatch方法就是

function (action) {
  typeof action === "function" ?
    action(dispatch, getState) :
    next(action)
}
// 這里的next方法,就是真正的store.dispatch方法
// 這里的dispatch是(action) => store.dispatch(action)

我們?cè)俳Y(jié)合redux-thunk的使用方法來分析一下,

function incrementAsync() {
  return dispatch => {
    setTimeout(() => {
      // Yay! Can invoke sync or async actions with `dispatch`
      dispatch(increment());
    }, 1000);
  };
}

這是使用redux-thunk時(shí)可以定義的異步action,我們觸發(fā)action的時(shí)候調(diào)用的是

dispatch(incrementAsync())

incrementAsync返回的是

function (dispatch) {
  setTimeout(() => {
    // Yay! Can invoke sync or async actions with `dispatch`
    dispatch(increment());
  }, 1000);
}

這個(gè)時(shí)候我們回想經(jīng)過中間件加工的dispatch方法:

function (action) {
  typeof action === "function" ?
    action(dispatch, getState) :
    next(action)
}
// 這里的next方法,就是真正的store.dispatch方法
// 這里的dispatch是(action) => store.dispatch(action)

action是一個(gè)函數(shù),所以action === "function" ?成立,那么就執(zhí)行action, 并把中間件接收到的dispatch方法((action) => store.dispatch(action))方法作為參數(shù)傳入,在異步方法執(zhí)行完之后再次觸發(fā)真正的action。如果action不是異步的,那么久直接返回一個(gè)對(duì)象,這個(gè)時(shí)候action === "function" ?不成立,就直接調(diào)用next,也就是原始的store.dispatch方法。

我們?cè)俳又?,如果我們有許多個(gè)中間件,那么沒一個(gè)中間件的next就是下一個(gè)中間件直到最后一個(gè)中間件調(diào)用store.dispatch為止。

以上的代碼非常繞,建議去專研一下源碼。這么精簡(jiǎn)的代碼包含了非常多的函數(shù)式編程的思想,也用到了裝飾器模式的原理,不得不說:

太燒腦啦/(ㄒoㄒ)/~~

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/78911.html

相關(guān)文章

  • 前端進(jìn)階資源整理

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

    BlackMass 評(píng)論0 收藏0
  • 寫一本關(guān)于 React.js 的小書

    摘要:因?yàn)楣ぷ髦幸恢痹谑褂?,也一直以來想總結(jié)一下自己關(guān)于的一些知識(shí)經(jīng)驗(yàn)。于是把一些想法慢慢整理書寫下來,做成一本開源免費(fèi)專業(yè)簡(jiǎn)單的入門級(jí)別的小書,提供給社區(qū)。本書的后續(xù)可能會(huì)做成視頻版本,敬請(qǐng)期待。本作品采用署名禁止演繹國(guó)際許可協(xié)議進(jìn)行許可 React.js 小書 本文作者:胡子大哈本文原文:React.js 小書 轉(zhuǎn)載請(qǐng)注明出處,保留原文鏈接以及作者信息 在線閱讀:http://huzi...

    Scorpion 評(píng)論0 收藏0
  • React 深入系列6:高階組件

    摘要:在項(xiàng)目中用好高階組件,可以顯著提高代碼質(zhì)量。高階組件的定義類比于高階函數(shù)的定義。高階函數(shù)接收函數(shù)作為參數(shù),并且返回值也是一個(gè)函數(shù)。 React 深入系列,深入講解了React中的重點(diǎn)概念、特性和模式等,旨在幫助大家加深對(duì)React的理解,以及在項(xiàng)目中更加靈活地使用React。 1. 基本概念 高階組件是React 中一個(gè)很重要且比較復(fù)雜的概念,高階組件在很多第三方庫(如Redux)中都...

    2shou 評(píng)論0 收藏0
  • 進(jìn)階2-2期】JavaScript深入之從作用域鏈理解閉包

    摘要:使用上一篇文章的例子來說明下自由變量進(jìn)階期深入淺出圖解作用域鏈和閉包訪問外部的今天是今天是其中既不是參數(shù),也不是局部變量,所以是自由變量。 (關(guān)注福利,關(guān)注本公眾號(hào)回復(fù)[資料]領(lǐng)取優(yōu)質(zhì)前端視頻,包括Vue、React、Node源碼和實(shí)戰(zhàn)、面試指導(dǎo)) 本周正式開始前端進(jìn)階的第二期,本周的主題是作用域閉包,今天是第7天。 本計(jì)劃一共28期,每期重點(diǎn)攻克一個(gè)面試重難點(diǎn),如果你還不了解本進(jìn)階計(jì)...

    simpleapples 評(píng)論0 收藏0
  • 前端資源系列(4)-前端學(xué)習(xí)資源分享&前端面試資源匯總

    摘要:特意對(duì)前端學(xué)習(xí)資源做一個(gè)匯總,方便自己學(xué)習(xí)查閱參考,和好友們共同進(jìn)步。 特意對(duì)前端學(xué)習(xí)資源做一個(gè)匯總,方便自己學(xué)習(xí)查閱參考,和好友們共同進(jìn)步。 本以為自己收藏的站點(diǎn)多,可以很快搞定,沒想到一入?yún)R總深似海。還有很多不足&遺漏的地方,歡迎補(bǔ)充。有錯(cuò)誤的地方,還請(qǐng)斧正... 托管: welcome to git,歡迎交流,感謝star 有好友反應(yīng)和斧正,會(huì)及時(shí)更新,平時(shí)業(yè)務(wù)工作時(shí)也會(huì)不定期更...

    princekin 評(píng)論0 收藏0

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

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<