面試還問redux?那我從頭手擼原始碼吧(中介軟體)

2021-08-30 02:02:49 字數 2832 閱讀 9120

昨天的文章手寫了一版redux的核心原始碼,redux庫除了資料的狀態管理還有一塊重要的內容那就是中介軟體,今天我還是嘗試將此部分原始碼完成。

react中管理資料的流程是單向的,就是說,從派發動作一直到發布訂閱觸發渲染是一條路走到頭,那麼如果想要在中間新增或是更改某個邏輯就需要找到action或是reducer來修改,有沒有更方便的做法呢?

而中介軟體(middleware)就是乙個可插拔的機制,如果想要擴充套件某個功能,比如新增日誌,在更新前後列印出state狀態,只需要將日誌中介軟體裝到redux上即可,於是便有了日誌功能,當不想使用時可再拿掉,非常方便。

目前有很多第三方的中介軟體安裝即可使用,比如剛剛提及的日誌中介軟體:redux-logger,使用npm安裝它:

npm install redux-logger

import from "./reducer";

import reduxlogger from "redux-logger";

複製**

裝載好中介軟體就在派發動作上擴充套件了相應的功能,這時我們正常編寫redux程式,當執行dispatch方法時會在控制台列印出state更新日誌:

[上傳中...(image-9cdcfb-1540517980322-3)]

以上就是乙個使用中介軟體的例子。

那麼中介軟體的執行原理是什麼呢?就用剛剛的日誌中介軟體舉例,它的功能是在state物件的更新前後分別輸出狀態,那麼肯定是在派發(dispatch)動作的那一刻去實現的,那我們改寫一下redux庫,將「列印日誌」功能新增到dispatch方法裡:

let temp = store.dispatch;//暫存原dispatch方法

store.dispatch = function(action) ;

複製**

複製**

return function (createstore)

}};複製**

通過函式引數就可以看到,三層函式分別傳入了中介軟體(middleware)、建立倉庫方法(createstore)和reducer函式,這正是我們裝載乙個中介軟體所需要的。

接下來我們的目標就是將中介軟體提供的dispatch覆蓋redux原有的dispatch方法,這樣就「裝載」好了中介軟體。

return function (createstore) }}

}複製**

有了通用寫法,我們自己模擬實現乙個日誌中介軟體:

function reduxlogger(store) `);

dispatch(action);

console.log(`更新後:$`);}}

}複製**

[上傳中...(image-d0df4a-1540517980322-2)]

洋蔥模型

洋蔥模型的概念似乎是在koa2框架中提出的,它是指中介軟體的執行機制,當多個中介軟體執行時,後乙個中介軟體會套在前乙個中介軟體的裡面:

[上傳中...(image-fef258-1540517980322-1)]

執行完乙個中介軟體會一直向裡走,直到最後乙個執行結束,再從內而外走出,就像是在剝洋蔥一樣。

compose方法

我們同樣使用洋蔥模型來寫乙個組合方法,以達到目的。

新建乙個compose.js,建立乙個組合函式:

/**

* 組合所有中介軟體

* @param middlewares

*/function compose(...middlewares)

}複製**

我的目標是當呼叫組合函式,傳入多個中介軟體,將所有的中介軟體組合成乙個函式:

var all = compose(middleware3, middleware2, middleware1);

all();//呼叫時,依次執行所有中介軟體

複製**

我們動手實現它。

寫之前我們先想一下,組合功能即是將「若干」個功能封裝為「乙個」功能,這正是函式式程式設計的收斂思想,es6中已經為我們提供了reduce函式,在這裡最合適不過了:

/**

* 組合所有中介軟體

* @param middlewares

*/function compose(...middlewares)

})(...args);

}}複製**

通過reduce函式,一步一步將後乙個中介軟體套到前乙個中介軟體之中,後乙個中介軟體的結果即前乙個的引數,這樣層層遞近,最終返回乙個大函式,即完成組合。

最後可以優化為箭頭函式的形式,顯得逼格更高一點:

function compose(...middlewares) 

複製**

完成中介軟體裝載

return function (createstore) );

//組合所有的中介軟體

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

//覆蓋原有的dispatch方法

return }}

}複製**

至此,redux庫的原始碼已經基本實現完畢。

多個中介軟體執行如下:

[上傳中...(image-3eec9c-1540517980322-0)]

這兩天從頭手寫了一遍redux庫發現redux的原始碼量並不大但是邏輯還是很複雜的,理清redux的流程是讀寫原始碼的前提。而中介軟體則是redux庫的乙個難點,主要是層層呼叫關係非常惱人,乙個好辦法是通過庫原始碼與中介軟體原始碼對比來分析,理清思路即可,如果還有時間我會嘗試再手寫一版react-redux庫,乙個是學習提高,二是應付面試。

redux教程(一) 理解redux

react的頁面應用越來越複雜,資料和狀態的管理也越來越複雜,甚至夾雜著ajax非同步請求對資料狀態的變更。不知從什麼時候開始 react框架的資料狀態的管理已經越來越難以控制和 redux就是針對難以處理的資料管理,提出的一種解決方案。它能夠讓你的頁面的資料管理更輕鬆。當問到為什麼要使用redux...

redux(一)初步讀懂配置redux流程

建立state.js let state export default state 定義action型別名常量count.js export const add action add action export const remove action remove action export con...

Redux學習筆記 Redux簡易開發步驟

該文章不介紹redux基礎,也不解釋各種亂亂的概念,網上一搜一大堆。只講使用redux開發乙個功能的步驟,希望可以類我的小白們,拜託它眾多概念的毒害,大牛請繞道!本文例項源 參考 react redux primary demo const render reactdom.render class ...