ReactRouter知識點
本文討論的React Router版本是V5以上的
react-router和react-router-dom的區(qū)別

為什么有時候我們看到如下的寫法:
寫法1:
import {Switch, Route, Router, browserHistory, Link} from 'react-router-dom';
寫法2:
import {Switch, Route, Router} from 'react-router';
import {BrowserRouter as Router, Link} from 'react-router-dom';
先簡單說下各自的功能:
react-router: 實現(xiàn)了路由的核心功能
react-router-dom(用于瀏覽器環(huán)境): 基于react-router,加入了在
瀏覽器運行環(huán)境下的一些功能,例如:Link組件,會渲染一個a標簽,Link組件源碼a標簽行; BrowserRouter和HashRouter 組件,前者使用pushState和popState事件構(gòu)建路由,后者使用window.location.hash和hashchange事件構(gòu)建路由。react-router-native: 基于react-router,類似react-router-dom,加入了react-native運行環(huán)境下的一些功能。
react-router-dom依賴react-router,所以我們使用npm安裝依賴的時候,只需要安裝相應(yīng)環(huán)境下的庫即可,不用再顯式安裝react-router?;跒g覽器環(huán)境的開發(fā),只需要安裝react-router-dom
如上所說,我們使用react開發(fā)web應(yīng)用,所以只需要安裝react-router-dom。
npm install react-router-dom --save
Router
所有路由器組件的通用低級接口。通常情況下,應(yīng)用程序會使用其中一個高級別路由器來代替
<BrowserRouter><HashRouter><MemoryRouter><NativeRouter><StaticRouter>
比如??<Router history="{browserHistory}"></Router> 與< BrowserRouter></BrowserRouter >表達的是一樣的意思
The most common use-case for using the low-level
is to synchronize a custom history with a state management lib like Redux or Mobx. Note that this is not required to use state management libs alongside React Router, it’s only for deep integration.
三種路由模式
本文檔中的 "history "和 "history對象 "是指history,包,它是React Router僅有的兩個主要依賴項之一(除了React本身),它提供了幾種不同的實現(xiàn),用于在各種環(huán)境中管理JavaScript的會話歷史。
React Router 是建立在 history 之上的。簡而言之,一個 history 知道如何去監(jiān)聽瀏覽器地址欄的變化, 并解析這個 URL 轉(zhuǎn)化為 location 對象, 然后 router 使用它匹配到路由,最后正確地渲染對應(yīng)的組件。
常用的 history 有三種形式, 但是你也可以使用 React Router 實現(xiàn)自定義的 history。
browserHistory hashHistory createMemoryHistory
Memory history 不會在地址欄被操作或讀取。這就解釋了我們是如何實現(xiàn)
服務(wù)器渲染的。同時它也非常適合測試和其他的渲染環(huán)境(像 React Native )。
用法
import React from "react";
import {
Router,
Switch,
Route,
Link
} from "react-router-dom";
import {createMemoryHistory} from 'history'
// This site has 3 pages, all of which are rendered
// dynamically in the browser (not server rendered).
//
// Although the page does not ever refresh, notice how
// React Router keeps the URL up to date as you navigate
// through the site. This preserves the browser history,
// making sure things like the back button and bookmarks
// work properly.
export default function BasicExample() {
return (
<Router history={createMemoryHistory()}>
<div>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/about">About</Link>
</li>
<li>
<Link to="/dashboard">Dashboard</Link>
</li>
</ul>
<hr />
{/*
A <Switch> looks through all its children <Route>
elements and renders the first one whose path
matches the current URL. Use a <Switch> any time
you have multiple routes, but you want only one
of them to render at a time
*/}
<Switch>
<Route exact path="/">
<Home />
</Route>
<Route path="/about">
<About />
</Route>
<Route path="/dashboard">
<Dashboard />
</Route>
</Switch>
</div>
</Router>
);
}
可點擊demo體驗,記得復(fù)制粘貼部分代碼
確實不會引起地址欄的變化
MemoryRouter與StaticRouter的區(qū)別
MemoryRouter :A
that keeps the history of your “URL” in memory (does not read or write to the address bar). Useful in tests and non-browser environments like React Native. A
that never changes location.This can be useful in server-side rendering scenarios when the user isn’t actually clicking around, so the location never actually changes. Hence, the name: static. It’s also useful in simple tests when you just need to plug in a location and make assertions on the render outpu
MemoryRouter主要是用于非瀏覽器環(huán)境,它的歷史記錄是放在內(nèi)存中的并不會改變地址欄
StaticRouter主要用于服務(wù)端渲染, StaticRouter是無狀態(tài)的,與BrowserRouter的區(qū)別就是這樣
BrowserRouter:A <Router> that uses the· HTML5 history API (pushState, replaceState and the popstate event) to keep your UI in sync with the URL.
這里我理解的無狀態(tài)就是o keep your UI in sync with the URL. StaticRouter不需要保持UI同步(以瀏覽器來說,我們的url變化,UI對應(yīng)更新,但可能是局部的,會保留部分狀態(tài)),由于服務(wù)端是無狀態(tài)的,我只要拿到對應(yīng)的組件渲染出HTML扔給客戶端就行
這是我的理解,歡迎其他同學補充
注意:SSR服務(wù)端渲染路由是要HTML5 history ,所以這里也是不拿HashRouter比較的原因
官網(wǎng)是用MemoryRouter做測試用,StaticRouter是用于服務(wù)端渲染,但是我覺得MemoryRouter也可以用于服務(wù)端渲染,因為它本身可以用于非瀏覽器環(huán)境
Vue官方也有提到



// src/server.tsx
import { Routes } from "@/routes";
import { createStore, StoreCtx } from "@/store";
import * as React from "react";
import { StaticRouter } from "react-router";
function ServerRender(req, context, initStore) {
return props => {
// hook 要在這、函數(shù)組件內(nèi)部調(diào)用
const value = createStore(initStore);
return (
<StoreCtx.Provider value={value}>
<StaticRouter location={req.url} context={context}>
<Routes />
</StaticRouter>
</StoreCtx.Provider>
);
};
}
參考文獻
https://reactrouter.com/core/guides/philosophy https://zhuanlan.zhihu.com/p/101129994 https://github.com/remix-run/react-router/issues/7166 https://segmentfault.com/a/1190000022066757
