摘要:概述前一章講了的,這一章講中很神奇的中間件。我們也可以使用中間件來擴展的功能。當然一樣的,這樣的中間件也已經存在了,日志的中間件也已經存在了查看效果資源源碼
0x000 概述
前一章講了redux的Action Creator,這一章講redux中很神奇的中間件。
0x001 手寫中間件在項目中,我們經常會有記錄一些事件或者在某些事件發生的時候做某些事的需求,比如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完成對數據的修改,現在我們希望記錄每一次對數據的修改,我們可以這么做
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:封裝成函數,可以,經常我們也是這么做的,但是不好
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,沒毛病,但是不夠優雅并且如果希望有多個中間件不太好辦,并且希望中間鍵可以串聯起來
const storeDispatch=store.dispatch store.dispatch= (action) => { console.log("action", action.type) storeDispatch(action) console.log("next state", store.getState()) } store.dispatch(action)
封裝3:多個中間件串聯
這里寫了兩個中間鍵,一個是前中間件,一個是后中間件,在執行 before(store)的時候,其實我們已經將store.dispatch替換成了before的dispatch,所以我們在after對dispatch第二次替換的時候,const storeDispatch = store.dispatch中的 store.dispatch其實是before.dispatch,所以,當我們執行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:優化中間件寫法
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 } } // 創建 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) // 發出 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是否是一個函數,如果是一個函數,那就直接執行這個函數,同時將dispatch作為參數,則在asyncAction我們就能直接訪問到dispatch了,就可以在asyncAction適當的時候再次dispatch了。
當然一樣的,這樣的中間件也已經存在了:redux-thunk,日志的中間件也已經存在了:redux-logger
import thunkMiddleware from "redux-thunk" import { createLogger } from "redux-logger" const store = createStore( counter, applyMiddleware( thunkMiddleware, createLogger() ) ) store.dispatch(increment())
查看效果
0x004 資源源碼
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/97936.html
摘要:的全稱是統一資源定位符英文,可以這么說,是一種標準,而網址則是符合標準的一種實現而已。渲染器,將組件渲染到頁面上。 0x000 概述 從這一章開始就進入路由章節了,并不直接從如何使用react-route來講,而是從路由的概念和實現來講,達到知道路由的本質,而不是只知道如何使用react-route庫的目的,畢竟react-route只是一個庫,是路由的一個實現而已,而不是路由本身。 ...
摘要:入門實例前端技術真是日新月異,搞完不搭配個數據流都不好意思了。關于的用法,這只是基礎入門的部分,還有的多的搞基操作,比如異步數據流和配合。 redux —— 入門實例 TodoListshowImg(https://segmentfault.com/img/bVtSeH); Tip 前端技術真是日新月異,搞完 React 不搭配個數據流都不好意思了。滿懷期待的心去翻了翻 flux,簡直...
摘要:異步實現設計需要增加三種通知異步請求發起的異步請求成功的異步請求失敗的示例代碼如下返回參數完全可以自定義。這種分別在請求開始前,請求成功后,請求失敗后發送。表示數據的有效性,他的作用是在異步請求發送失敗后,告訴當前的數據是過時的數據。 說明:對Redux不了解的同學可先看看這篇文章Redux技術架構簡介(一) 前言 這里說的Redux異步實現,是專指Redux中的異步Action實現,...
摘要:接下來的函數就有點難度了,讓我們一行一行來看。上面實際的含義就是將數組每一個執行的返回值保存的數組中。需要注意的是,方法返回值并不是數組,而是形如初始值的經過疊加處理后的操作。從而實現異步的。 這段時間都在學習Redux,感覺對我來說初學難度很大,中文官方文檔讀了好多遍才大概有點入門的感覺,小小地總結一下,首先可以看一下Redux的基本流程:showImg(https://segm...
閱讀 2602·2021-09-26 10:17
閱讀 3229·2021-09-22 15:16
閱讀 2136·2021-09-03 10:43
閱讀 3266·2019-08-30 11:23
閱讀 3662·2019-08-29 13:23
閱讀 1308·2019-08-29 11:31
閱讀 3691·2019-08-26 13:52
閱讀 1400·2019-08-26 12:22