mp.weixin.qq.com/s/0y-79NrBrKS-vta_iI5Tcg
一、依賴(Dependencies)在一般的SPA開發(fā)中,路由管理非常重要。作為反應(yīng)技術(shù)系統(tǒng)的一部分,官方維護(hù)的反應(yīng)路由器是首選的路由庫。
應(yīng)用Redux模式后,React-Router與Redux的合作出現(xiàn)了新的問題。需要帶路線進(jìn)店管理嗎?如何將路線帶入店鋪進(jìn)行管理?這些都是需要考慮的問題。我們后面會(huì)討論第一個(gè)問題,為了解決上面提到的第二個(gè)問題,輕量級(jí)擴(kuò)展庫React-Router-Redux應(yīng)運(yùn)而生并被廣泛使用。
另外需要注意的是,React-Router和React-Router-Redux長期以來是兩個(gè)獨(dú)立的庫,但是在React-Router 4.x版本之后,React-Router-Redux已經(jīng)成為React-Router 4 . x的一部分
本文不打算介紹這兩種依賴庫的具體用法(具體用法請參考官方文檔和教程),主要闡述它們的實(shí)現(xiàn)方法和原理,并總結(jié)具體的實(shí)踐方法和注意事項(xiàng)。在介紹主要內(nèi)容之前,先簡要介紹下兩個(gè)庫的功能:
React-Router React-Router 做的最重要的事就是將瀏覽器 URL 與程序聯(lián)系起來(借助 history 庫),它為 React 提供了聲明式的路由系統(tǒng),通過其提供的導(dǎo)航組件,我們能夠方便地使用 URL 來控制狀態(tài)的變化和組件的切換。React-Router-Redux 按照官方的說法,其實(shí)現(xiàn)了「deep integration of react-router and redux」,即 React-Router 與 Redux 的深度集成,它將路由完全納入 store 中進(jìn)行管理,使 store 成為了 URL(或者說是 history)的數(shù)據(jù)來源,也使我們能夠通過 dispatch action 的方式來修改 URL。我們將在后文介紹它的實(shí)現(xiàn)原理。二、實(shí)踐Redux架構(gòu)中不必涉及路由狀態(tài)。在一些簡單的應(yīng)用場景中,只需使用聲明性組件(路由器、路由、鏈接等)就可以方便地實(shí)現(xiàn)URL導(dǎo)航。)由React-Router提供。在一些復(fù)雜的場景中,只要遵循React單向數(shù)據(jù)流模式和使用方法,也可以讀取路由信息并觸發(fā)變更,如下圖所示。(有關(guān)用法,請參考反應(yīng)路由器文檔和教程。)
但是在這里,我們主要討論將路由狀態(tài)納入Redux架構(gòu)的情況。本部分的以下部分將分為兩個(gè)部分:
手動(dòng)管理,也就是不使用 React-Router-Redux;借助 React-Router-Redux 管理,這也是討論的重點(diǎn)。2.1、手動(dòng)管理 (Mannually)不需要其他庫的幫助,一個(gè)簡單的方法就是手動(dòng)將路由狀態(tài)帶入商店進(jìn)行管理,當(dāng)URL發(fā)生變化時(shí)同步修改商店中的狀態(tài)。
如上所示,在手動(dòng)同步中,路由信息通過一組Redux機(jī)制存儲(chǔ)在存儲(chǔ)中。歷史是數(shù)據(jù)源。通過監(jiān)聽歷史,在URL狀態(tài)改變時(shí)調(diào)度相應(yīng)的動(dòng)作(例如,type = LOCATION_CHANGE),通過添加的減壓器將位置信息同步到店鋪。這樣,組件就可以獲得商店中的位置狀態(tài)信息,這也是目前react-reduce-starter-kit采用的方式。
這種相對原始的方式有一定的缺點(diǎn):
沒有將路由完全納入 Redux 管理。路由不支持 time travel。history 實(shí)際也是 react-router 的路由數(shù)據(jù)來源,這就導(dǎo)致我們 store 中存儲(chǔ)的 location 數(shù)據(jù)與 react-router 并不一定同步。(例如,這會(huì)導(dǎo)致文末討論的重復(fù)渲染問題)2.2、使用 React-Router-Redux我們來討論一下開頭提出的第一個(gè)問題:是否需要將路線帶入店內(nèi)進(jìn)行管理?雖然react-router-redux從4.x版本的react-router開始就成為其中的一部分,但官方對于是否應(yīng)該在項(xiàng)目中使用提出了建議:
希望在項(xiàng)目中使用完全使用 store 管理路由數(shù)據(jù)希望使用 dispatch action 的方式進(jìn)行導(dǎo)航(修改路由)希望調(diào)試時(shí)路由支持 time travel以上是使用React-Router-Redux的原理,當(dāng)然在一定程度上也可以是決定將路由納入店鋪管理的原理。我想我們可以再補(bǔ)充兩個(gè):
項(xiàng)目抽象中,路由信息應(yīng)該作為一種全局的狀態(tài)管理有 Redux 強(qiáng)迫癥2.2.1、原理通過圖表了解React-Router-Redux的實(shí)現(xiàn)原理。
上圖其實(shí)就是React-Router-Redux如何同步URL與狀態(tài)的過程。在程序中,主要通過以下重要的API實(shí)現(xiàn):
routerMiddleware 與 routerReducer routerMiddleware 與 routerReducer 的共同作用,讓我們能夠處理兩種 action 類型:一種類型為 LOCATION_CHANGE,與手動(dòng)管理過程中相同,它負(fù)責(zé)修改 store 存儲(chǔ);另一種類型為 CALL_HISTORY_METHOD,這類 action 一般會(huì)在組件內(nèi)派發(fā),它不負(fù)責(zé) state 的修改,通過 routerMiddleware 后,會(huì)被轉(zhuǎn)去調(diào)用 history 方法(如 push, replace 等),以修改 URL 狀態(tài)。syncHistoryWithStore 顧名思義,這個(gè)方法就是處理路由與 store 中信息同步的重要方法。通過這個(gè)方法,我們能獲得一個(gè)新的、增強(qiáng)版的 history 對象,這個(gè)對象重寫了 history.listen 方法,原有的 history.listen 只負(fù)責(zé) action (LOCATION_CHANGE) 的派發(fā),新的 history.listen 則只監(jiān)聽 store 的變化(使用了 store.subscribe),所以當(dāng)我們在程序內(nèi)調(diào)用 history.listen 時(shí),實(shí)際上是在監(jiān)聽 store 中的路由信息。2.2.2、實(shí)踐:location as a prop在實(shí)際項(xiàng)目應(yīng)用中,合理的實(shí)踐模式如下。
也就是說,位置或子屬性(如location.pathname等。)作為屬性信息逐層傳遞給與路由信息有關(guān)的子組件,類似于react-router最初的使用方法,不同的是在改變URL時(shí)使用了調(diào)度動(dòng)作。
三.建議3.1。謹(jǐn)慎使用state.routing
一般使用React-Router-Redux時(shí),路由信息會(huì)以路由的形式體現(xiàn)出來。商店中的locationbeforetransition。在上面的實(shí)踐中,我們沒有直接從商店獲得這個(gè)狀態(tài)。其實(shí)官方不推薦。從名字上,作者已經(jīng)明確提醒我們,這是一個(gè)不斷變化的價(jià)值。
您不應(yīng)該直接從Redux存儲(chǔ)中讀取位置狀態(tài)。這是因?yàn)镽eact Router異步運(yùn)行(處理動(dòng)態(tài)加載組件之類的事情),并且您的組件樹可能還沒有與您的Redux狀態(tài)同步更新。您應(yīng)該依賴React Router傳遞的道具,因?yàn)樗鼈冎挥性谔幚硗晁挟惒酱a后才會(huì)更新。
不應(yīng)直接從Redux存儲(chǔ)讀取路由狀態(tài)。這是因?yàn)榉磻?yīng)路由器的行為是異步的(例如,處理組件的動(dòng)態(tài)加載等)。),所以你的組件樹可能跟不上Redux狀態(tài)的變化。您應(yīng)該依賴React Router傳遞的屬性,這樣可以確保這些值在所有異步操作完成之前不會(huì)更新。
當(dāng)路由中的值發(fā)生變化時(shí),反應(yīng)路由器可能尚未完成組件樹的更新,使用此值可能會(huì)導(dǎo)致一些問題。因此,作者仍然建議我們通過傳遞位置屬性來讀取路由信息,以確保反應(yīng)路由器完成處理。
3.2.僅傳遞必要的路由信息
只傳遞必要的信息,比如location.pathname和location.query.page,而不是傳遞整個(gè)位置。這樣可以盡可能避免可能的重復(fù)渲染。
3.3.僅使用調(diào)度操作來修改路線
實(shí)際上,除了使用鏈路組件之外,在使用React-Router-Redux之后,還有許多方法可以修改路由信息,例如:
history.methodcontext.router.methoddispatch ROUTER-ACTION我還是建議只通過調(diào)度動(dòng)作修改路由,這樣更符合Redux流程,也方便解耦組件。在實(shí)際應(yīng)用中,應(yīng)該使用統(tǒng)一的動(dòng)作創(chuàng)建器來創(chuàng)建用于修改路線的動(dòng)作。
3.4.小心使用路由器高級(jí)組件(裝飾器)
React-Router提供了withRouter高級(jí)組件,以便該組件可以訪問路由狀態(tài)信息(匹配、位置、歷史),但是一旦引用的路由屬性發(fā)生變化,它將觸發(fā)重新呈現(xiàn)過程。如果使用不當(dāng),可能會(huì)導(dǎo)致組件的冗余重新渲染。
四、常見問題4.1、重渲染(重復(fù)渲染)問題
在使用React-Router和路由組件進(jìn)行異步加載后,一個(gè)常見的問題是在組件切換時(shí)出現(xiàn)意外的重復(fù)呈現(xiàn)。在正常情況下(當(dāng)代碼未劃分時(shí)),當(dāng)反應(yīng)路由器切換路由組件時(shí),過程如下:
代碼分割后,異步加載路由組件,過程如下:
因?yàn)榻M件A導(dǎo)入了位置或者它的相關(guān)屬性,道具,位置的改變導(dǎo)致了道具的改變。此時(shí)由于組件B還沒有加載成功,所以卸載之前組件A沒有必要重新渲染。
通常,此問題是由于不正確使用已更改的路由信息引起的,如上面的狀態(tài)路由信息,以及不同步的狀態(tài)路由和反應(yīng)路由器路由信息。解決方案:參考上述做法,使用Route組件注入的位置數(shù)據(jù)進(jìn)行路由信息傳輸。
動(dòng)詞 (verb的縮寫)引文
https://github.com/reactjs/react-router-reduxhttps://github.com/reactjs/react-router-tutorialhttps://github.com/ReactTraining/history[關(guān)于提交]
如果有原創(chuàng)的好文章投稿,請直接發(fā)消息到官方號(hào)。
1.《annually React 路由狀態(tài)管理總結(jié)》援引自互聯(lián)網(wǎng),旨在傳遞更多網(wǎng)絡(luò)信息知識(shí),僅代表作者本人觀點(diǎn),與本網(wǎng)站無關(guān),侵刪請聯(lián)系頁腳下方聯(lián)系方式。
2.《annually React 路由狀態(tài)管理總結(jié)》僅供讀者參考,本網(wǎng)站未對該內(nèi)容進(jìn)行證實(shí),對其原創(chuàng)性、真實(shí)性、完整性、及時(shí)性不作任何保證。
3.文章轉(zhuǎn)載時(shí)請保留本站內(nèi)容來源地址,http://f99ss.com/fangchan/1028775.html