當前的分析版本是 v52.0,最新提交為:專案由 lerna 管理,在根目錄下執行yarn
您可以為專案安裝依賴項。 繼續在根目錄下執行yarn build
會進入 reaact-router、react-router-dom 等目錄進行打包,打包工具是 rollup,會打包 esm、cjs、umd 等結果。
react-router-dom:軟體包 react-router-dom
/users/songjp/fe/mime/react-router/packages/react-router-dom├──browserrouter.js├──hashrouter.js├──link.js├──memoryrouter.js├──n**link.js├──prompt.js├──readme.md├──redirect.js├──route.js├──router.js├──staticrouter.js├──switch.js├──es| ├browserrouter.js| ├hashrouter.js| ├link.js| ├memoryrouter.js| ├n**link.js| ├prompt.js| ├redirect.js| ├route.js| ├router.js| ├staticrouter.js| ├switch.js| ├generatepath.js| ├matchpath.js| ├warnaboutdeprecatedesmimport.js| └withrouter.js├──generatepath.js├──index.js├──jest.config.js├──matchpath.js├──modules| ├browserrouter.js| ├hashrouter.js| ├link.js| ├n**link.js| ├index.js| └utils├──package.json├──rollup.config.js├──warnaboutdeprecatedcjsrequire.js└──withrouter.js
您可能會有疑問:
為什麼根目錄下有瀏覽器路由器?js,還有es browserrouterjs 和模組 BrowserRouterjs ?為什麼根目錄下有路由器?js,有es路由器js,但沒有模組路由器JS直接說出了結論:
彙總根據模組索引打包js 打包,即原始碼在 modules 目錄下,react-router-dom 的原始碼在 modules 目錄下,主要是 browserrouter、hashrouter、link、n**link 元件,至於 router 元件、switch 元件等,其實在 react-router 倉庫裡。 至於根目錄下的browserrouterjs 主要是為了相容性require("react-router-dom/%s")
實際上應該更多地使用require("react-router-dom").%s
es 目錄js 主要是為了相容性import %s from "react-router-dom/es/%s
這樣的引用方式,其實更值得推薦import from "react-router-dom"
引用的方式是只要注意 modules 目錄,es 目錄下的檔案和根目錄下的檔案都是為了相容一些元件引用
通常我們像這樣使用 react-router-dom:
import from "./react-router-dom"; home about users
讓我們從browserrouter元件開始。
// react-router-dom/browserrouter.jsimport from "history";class browserrouter extends react.component }
browserrouter 元件實際上通過呼叫 history 中的 createbrowserhistory 方法來建立乙個 history 物件。 歷史記錄中有乙個 CreateTransitionManager 檔案,它在內部實現了觀察者模式:// history/createtransitionmanager.jslet listeners = const appendlistener = (fn) => listeners.push(listener) return ()=> }const notifylisteners = (.args) =>
當 history 物件本身觸發 popstate 事件或歷史記錄時替換或歷史記錄push 方法,notifylisteners 被觸發以通知所有觀察者。
而 react-router 中的 router 元件實際上是它是觀察者。它內部有乙個位置狀態,並且它訂閱了歷史記錄更改
// react-router/router.jsif (!props.staticcontext) )else }
當歷史記錄更改時,位置的狀態也會更改。 此狀態也用作 routercontext提供者將繼續傳遞。
// react-router/router.js
作為乙個真正的路由元件(渲染元件),它在內部確定從 routercontext 傳遞的位置值,以及它自己的路徑(例如確定是否存在匹配項:// react-router/route.jsconst match = this.props.computedmatch? this.props.computedmatch // already computed the match for us: this.props.path? matchpath(location.pathname, this.props): context.match;
匹配呈現子項:// react-router/route.js
從上面可以看出,支援各種孩子。 對應路由元件的元件引數、渲染引數和子引數。
在 BrowserRouter 的情況下,它只是將 CreateBrowserHistory 替換為 CreateHashHistory,因此最終的邏輯差異在於 npm 包 History。
// react-router-dom/hashrouter.jsimport react from "react";import from "history";class hashrouter extends react.component }export default hashrouter;
hashrouter 與 browserrouter 有什麼共同點:
當我們點選鏈結元件進行跳轉時,我們呼叫其中的推送方法(browserrouter 或 hashrouter)來更改 url。 對於歷史模式,它是通過歷史PushState,對於雜湊模式,是更改視窗location.hash。在各自的推送方法中,它們會呼叫內部的 setstate 方法,該方法會通知每個底層路由元件最新的路由資訊,每個路由元件會通過匹配最新的路由資訊來判斷是否需要顯示。 hashrouter 和 browserrouter 之間的區別:
什麼時候回滾前進的路由時間:歷史模式主要是監聽popstate事件,獲取最新的路由資訊(不,其實在觸發popstate的時候,url已經變了,所以直接把url資訊傳遞給路由),然後通過setstate通知路由元件。 請注意,popstate 事件稱為歷史記錄pushstate() 和歷史replaceState() 不執行,但僅在歷史記錄時執行back(),history.go(),history.forward() (當單擊瀏覽器後退按鈕時,它實際上等同於呼叫歷史記錄。back(),所以 popstate 事件也會被觸發)。參考:PopState MDN:對於hash模式,主要監聽hashchange事件,獲取最新的路由資訊(同上),通過setstate通知路由元件。