對(duì)react中間件的理解
一、是什么?
中間件(Middleware
)在計(jì)算機(jī)中,是介于應(yīng)用系統(tǒng)和系統(tǒng)軟件之間的一類軟件,它使用系統(tǒng)軟件所提供的基礎(chǔ)服務(wù)(功能),銜接網(wǎng)絡(luò)應(yīng)用上的各個(gè)部分或不同的應(yīng)用,能夠達(dá)到資源共享、功能共享的目的
我們知道redux
整個(gè)工作流程,當(dāng)action
發(fā)出之后,reducer
立即算出state
,整個(gè)過程是一個(gè)同步的操作。
那么如果要支持異步操作,或者支持錯(cuò)誤處理、日志監(jiān)控,就可以使用上中間件。
Redux中,中間件就是放在就是在dispatch過程,在分發(fā)action進(jìn)行攔截處理,如上圖
其本質(zhì)上一個(gè)函數(shù),對(duì)store.dispatch方法進(jìn)行了改造,在發(fā)出 Action和執(zhí)行 Reducer這兩步之間,添加了其他功能
二、常用的中間件
redux-thunk
:用于異步操作
redux-logger
:用于日志記錄
redux-promise
redux-saga
上述的中間件都需要通過applyMiddlewares
進(jìn)行注冊(cè),作用是將所有的中間件組成一個(gè)數(shù)組,依次執(zhí)行,然后作為第二個(gè)參數(shù)傳入到createStore中
import { createStore, applyMiddleware } from 'redux' import thunk from 'redux-thunk' import createLogger rom 'redux-logger' const logger = createLogger() const store = createStore(reducer, applyMiddleware(thunk, logger)) // 按順序執(zhí)行 從右到左
logger實(shí)現(xiàn)
// 自己修改dispatch,增加logger let next = store.dispatch store.dispatch = function dispatchAndLog(action) { console.log('dispatching', action) next(action) console.log('next state', store.getState()) }
redux-thunk
添加了thunk中間件之后,就可以進(jìn)行異步操作
redux-thunk是官網(wǎng)推薦的異步處理中間件
默認(rèn)情況下的dispatch(action),action需要是一個(gè)JavaScript的對(duì)象
redux-thunk
中間件會(huì)判斷你當(dāng)前傳進(jìn)來的數(shù)據(jù)類型,如果是一個(gè)函數(shù),將會(huì)給函數(shù)傳入?yún)?shù)值(dispatch,getState)dispatch
函數(shù)用于我們之后再次派發(fā)actiongetState
函數(shù)考慮到我們之后的一些操作需要依賴原來的狀態(tài),用于讓我們可以獲取之前的一些狀態(tài)
所以dispatch可以寫成下述函數(shù)的形式:
const getHomeMultidataAction = () => { return (dispatch) => { axios.get("http://xxx.xx.xx.xx/test").then(res => { const data = res.data.data; dispatch(changeBannersAction(data.banner.list)); dispatch(changeRecommendsAction(data.recommend.list)); }) } }
dispatch(addTodo(text)) dispatch(addTodoAsync(text))
redux數(shù)據(jù)流圖:
三、實(shí)現(xiàn)原理
首先看看applyMiddlewares的源碼
export default function applyMiddleware(...middlewares) { return (createStore) => (reducer, preloadedState, enhancer) => { var store = createStore(reducer, preloadedState, enhancer); 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} } }
所有中間件被放進(jìn)了一個(gè)數(shù)組chain,然后嵌套執(zhí)行,最后執(zhí)行store.dispatch。可以看到,中間件內(nèi)部(middlewareAPI)可以拿到getState和dispatch這兩個(gè)方法
在上面的學(xué)習(xí)中,我們了解到了redux-thunk的基本使用
內(nèi)部會(huì)將dispatch進(jìn)行一個(gè)判斷,然后執(zhí)行對(duì)應(yīng)操作,原理如下:
function patchThunk(store) { letnext = store.dispatch; function dispatchAndThunk(action) { if (typeof action === "function") { action(store.dispatch, store.getState); } else { next(action); } } store.dispatch = dispatchAndThunk; }
實(shí)現(xiàn)一個(gè)日志輸出的原理也非常簡(jiǎn)單,如下:
let next = store.dispatch; function dispatchAndLog(action) { console.log("dispatching:", addAction(10)); next(addAction(5)); console.log("新的state:", store.getState()); } store.dispatch = dispatchAndLog;
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
React項(xiàng)目動(dòng)態(tài)設(shè)置title標(biāo)題的方法示例
這篇文章主要介紹了React項(xiàng)目動(dòng)態(tài)設(shè)置title標(biāo)題的方法示例,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-09-09React Router 如何使用history跳轉(zhuǎn)的實(shí)現(xiàn)
這篇文章主要介紹了React Router 如何使用history跳轉(zhuǎn)的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-04-04react-navigation 如何判斷用戶是否登錄跳轉(zhuǎn)到登錄頁的方法
本篇文章主要介紹了react-navigation 如何判斷用戶是否登錄跳轉(zhuǎn)到登錄頁的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-12-12Input標(biāo)簽自動(dòng)校驗(yàn)功能去除實(shí)現(xiàn)
這篇文章主要為大家介紹了Input標(biāo)簽的自動(dòng)拼寫檢查功能去除實(shí)現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-07-07react-router browserHistory刷新頁面404問題解決方法
本篇文章主要介紹了react-router browserHistory刷新頁面404問題解決方法,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2017-12-12React中如何實(shí)現(xiàn)受控組件與非受控組件
在 React 開發(fā)里,組件可分為受控組件和非受控組件,這篇文章將為大家介紹一下它們的實(shí)現(xiàn)原理,方法,區(qū)別,作用和應(yīng)用場(chǎng)景是什么,希望對(duì)大家有所幫助2025-03-03