昨天的文章手寫了一版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 ...