摘要:概述前一章講了的,這一章講中很神奇的中間件。我們也可以使用中間件來擴展的功能。當然一樣的,這樣的中間件也已經(jīng)存在了,日志的中間件也已經(jīng)存在了查看效果資源源碼
0x000 概述
前一章講了redux的Action Creator,這一章講redux中很神奇的中間件。
0x001 手寫中間件在項目中,我們經(jīng)常會有記錄一些事件或者在某些事件發(fā)生的時候做某些事的需求,比如api接口鑒權操作、日志記錄操作等,一般我們都可以用中間件來完成,中間件具有可拔插、可擴展的特點。我們也可以使用中間件來擴展redux的功能。
記錄每一次的action和state變化
我們在之前是這么使用redux的:
import {createStore} from "redux" function counter(state = 0, action) { switch (action.type) { case "INCREMENT": return state + 1 default: return state } } let store = createStore(counter) store.subscribe(() => { // console.log(store.getState()) }) const ACTION_INCREMENT = "INCREMENT" const increment = () => { return { type: ACTION_INCREMENT } } const action = increment() store.dispatch(action) store.dispatch(action) store.dispatch(action)
通過store.dispatch完成對數(shù)據(jù)的修改,現(xiàn)在我們希望記錄每一次對數(shù)據(jù)的修改,我們可以這么做
console.log("action", action.type) store.dispatch(action) console.log("next state", store.getState()) console.log("action", action.type) store.dispatch(action) console.log("next state", store.getState()) console.log("action", action.type) store.dispatch(action) console.log("next state", store.getState())
效果很明顯,豬才會這么做
封裝1:封裝成函數(shù),可以,經(jīng)常我們也是這么做的,但是不好
const dispatch = (store, action) => { console.log("action", action.type) store.dispatch(action) console.log("next state", store.getState()) } dispatch(store, action)
封裝2:hack掉store.dispatch,沒毛病,但是不夠優(yōu)雅并且如果希望有多個中間件不太好辦,并且希望中間鍵可以串聯(lián)起來
const storeDispatch=store.dispatch store.dispatch= (action) => { console.log("action", action.type) storeDispatch(action) console.log("next state", store.getState()) } store.dispatch(action)
封裝3:多個中間件串聯(lián)
這里寫了兩個中間鍵,一個是前中間件,一個是后中間件,在執(zhí)行 before(store)的時候,其實我們已經(jīng)將store.dispatch替換成了before的dispatch,所以我們在after對dispatch第二次替換的時候,const storeDispatch = store.dispatch中的 store.dispatch其實是before.dispatch,所以,當我們執(zhí)行store.dispatch(increment())的時候,調用鏈其實是:store#dispatch=after#dispatch -> before#dispatch -> before#console.log -> store#dispatch -> after#console.log
const before = (store) => { const storeDispatch = store.dispatch const dispatch=(action) => { console.log("before", action.type,store.getState()) storeDispatch(action) } store.dispatch = dispatch } const after = (store) => { const storeDispatch = store.dispatch const dispatch = (action) => { storeDispatch(action) console.log("after",action.type,store.getState()) } store.dispatch=dispatch } before(store) after(store) store.dispatch(increment())
查看輸出:
封裝4:隱藏hack,減少樣板代碼
const before = (store) => { const storeDispatch = store.dispatch return (action) => { console.log("before", action.type, store.getState()) storeDispatch(action) } } const after = (store) => { const storeDispatch = store.dispatch return (action) => { storeDispatch(action) console.log("after", action.type, store.getState()) } } const applyMiddleware = (store, ...middlewares) => { middlewares.reverse() middlewares.forEach(middleware => { store.dispatch = middleware(store) }) } applyMiddleware(store, before, after) store.dispatch(increment())
封裝5:不使用 hack
const before = (store) => { return (storeDispatch) => { return (action) => { console.log("before", action.type, store.getState()) storeDispatch(action) } } } const after = (store) => { return (storeDispatch) => { return (action) => { storeDispatch(action) console.log("after", action.type, store.getState()) } } } const applyMiddleware = (store, ...middlewares) => { middlewares.reverse() let storeDispatch = store.dispatch middlewares.forEach(middleware => { storeDispatch = middleware(store)(storeDispatch) }) // store.dispatch = storeDispatch return {...store, ...{dispatch: storeDispatch}} } store = applyMiddleware(store, before, after) store.dispatch(increment())
封裝6:優(yōu)化中間件寫法
const before = store => storeDispatch => action => { console.log("before", action.type, store.getState()) return storeDispatch(action) } const after = store => storeDispatch => action => { let result = storeDispatch(action) console.log("after", action.type, store.getState()) return result }
最終的完整代碼
import {createStore} from "redux" // reducer function counter(state = 0, action) { switch (action.type) { case "INCREMENT": return state + 1 default: return state } } // 創(chuàng)建 store let store = createStore(counter) // action const ACTION_INCREMENT = "INCREMENT" // action creator const increment = () => { return { type: ACTION_INCREMENT } } // 前中間件 const before = store => storeDispatch => action => { console.log("before", action.type, store.getState()) return storeDispatch(action) } // 后中間件 const after = store => storeDispatch => action => { let result = storeDispatch(action) console.log("after", action.type, store.getState()) return result } // 應用中間件 const applyMiddleware = (store, ...middlewares) => { middlewares.reverse() let storeDispatch = store.dispatch middlewares.forEach(middleware => { storeDispatch = middleware(store)(storeDispatch) }) // store.dispatch = storeDispatch return {...store, ...{dispatch: storeDispatch}} } // 返回了新的 store store = applyMiddleware(store, before, after) // 發(fā)出 action store.dispatch(increment())0x002 redux applyMiddleware
前面寫了一個applyMiddleware方法,雖然可以用,但是官方其實也提供了這個方法,并且比我們寫的更好一點
const before = store => storeDispatch => action => { console.log("before", action.type, store.getState()) return storeDispatch(action) } const after = store => storeDispatch => action => { let result = storeDispatch(action) console.log("after", action.type, store.getState()) return result } let store = createStore(counter, applyMiddleware(before, after)) store.dispatch(increment())
可以看出來,相較于我們自己寫的`applyMiddleware`,官方提供的可以直接傳遞給`createStore`,而無需在次對`store`進行操作。0x003 異步action
const before = store => storeDispatch => action => { console.log("before", action.type, store.getState()) return storeDispatch(action) } const after = store => storeDispatch => action => { let result = storeDispatch(action) console.log("after", action.type, store.getState()) return result } const asyncAction=()=>{ return (dispatch)=>{ setInterval(()=>{ dispatch(increment()) },1000) } } const asyncMiddleware = store => storeDispatch => action => { if (typeof action === "function") { return action(storeDispatch) } else { return storeDispatch(action) } } let store = createStore(counter, applyMiddleware(asyncMiddleware,before,after)) store.dispatch(asyncAction())
這里寫了一個asyncMiddleware,他判斷傳入的action是否是一個函數(shù),如果是一個函數(shù),那就直接執(zhí)行這個函數(shù),同時將dispatch作為參數(shù),則在asyncAction我們就能直接訪問到dispatch了,就可以在asyncAction適當?shù)臅r候再次dispatch了。
當然一樣的,這樣的中間件也已經(jīng)存在了:redux-thunk,日志的中間件也已經(jīng)存在了:redux-logger
import thunkMiddleware from "redux-thunk" import { createLogger } from "redux-logger" const store = createStore( counter, applyMiddleware( thunkMiddleware, createLogger() ) ) store.dispatch(increment())
查看效果
0x004 資源源碼
文章版權歸作者所有,未經(jīng)允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://systransis.cn/yun/97936.html
摘要:的全稱是統(tǒng)一資源定位符英文,可以這么說,是一種標準,而網(wǎng)址則是符合標準的一種實現(xiàn)而已。渲染器,將組件渲染到頁面上。 0x000 概述 從這一章開始就進入路由章節(jié)了,并不直接從如何使用react-route來講,而是從路由的概念和實現(xiàn)來講,達到知道路由的本質,而不是只知道如何使用react-route庫的目的,畢竟react-route只是一個庫,是路由的一個實現(xiàn)而已,而不是路由本身。 ...
摘要:入門實例前端技術真是日新月異,搞完不搭配個數(shù)據(jù)流都不好意思了。關于的用法,這只是基礎入門的部分,還有的多的搞基操作,比如異步數(shù)據(jù)流和配合。 redux —— 入門實例 TodoListshowImg(https://segmentfault.com/img/bVtSeH); Tip 前端技術真是日新月異,搞完 React 不搭配個數(shù)據(jù)流都不好意思了。滿懷期待的心去翻了翻 flux,簡直...
摘要:異步實現(xiàn)設計需要增加三種通知異步請求發(fā)起的異步請求成功的異步請求失敗的示例代碼如下返回參數(shù)完全可以自定義。這種分別在請求開始前,請求成功后,請求失敗后發(fā)送。表示數(shù)據(jù)的有效性,他的作用是在異步請求發(fā)送失敗后,告訴當前的數(shù)據(jù)是過時的數(shù)據(jù)。 說明:對Redux不了解的同學可先看看這篇文章Redux技術架構簡介(一) 前言 這里說的Redux異步實現(xiàn),是專指Redux中的異步Action實現(xiàn),...
摘要:接下來的函數(shù)就有點難度了,讓我們一行一行來看。上面實際的含義就是將數(shù)組每一個執(zhí)行的返回值保存的數(shù)組中。需要注意的是,方法返回值并不是數(shù)組,而是形如初始值的經(jīng)過疊加處理后的操作。從而實現(xiàn)異步的。 這段時間都在學習Redux,感覺對我來說初學難度很大,中文官方文檔讀了好多遍才大概有點入門的感覺,小小地總結一下,首先可以看一下Redux的基本流程:showImg(https://segm...
閱讀 2613·2021-09-26 10:17
閱讀 3236·2021-09-22 15:16
閱讀 2145·2021-09-03 10:43
閱讀 3271·2019-08-30 11:23
閱讀 3667·2019-08-29 13:23
閱讀 1315·2019-08-29 11:31
閱讀 3699·2019-08-26 13:52
閱讀 1404·2019-08-26 12:22