其他章節請看:
react 路由
本篇首先講解路由原理,接着以一個基礎路由示例為起點講述路由最基礎的知識,然后講解嵌套路由、路由傳參,最后講解路由組件和一般組件的區別,以及編程式導航。
Tip:我們要接手的 react 項目是:spug_web。
什么是路由
路由就是根據不同的 url(網址) 返回不同的頁面(數據)。如果這個工作在后端做(或者說由后端程序員做),就是后端路由;在前端做就是前端路由。
平時總說的 SPA(單頁面應用)就是前后端分離的基礎上,再加一層前端路由。
react 路由原理
下面通過一個js 庫(history)來演示一下路由的原理:
<body>
請在瀏覽器控制台下體驗!
<!-- https://github.com/remix-run/history/blob/dev/docs/installation.md -->
<script src="https://unpkg.com/history/umd/history.production.min.js"></script>
<script>
let myHistory = window.HistoryLibrary.createBrowserHistory()
let unlisten = myHistory.listen(({ location, action }) => {
console.log(action, location.pathname)
});
</script>
</body>
訪問頁面,瀏覽器 url 為 http://127.0.0.1:5500/public/test.html
Tip:筆者在 vscode 中安裝 “open in browser” 插件,直接右鍵選擇 “Open with Live Server” 即可。
打開控制台進行測試:
> myHistory.push('/home')
PUSH /home
url 變為:http://127.0.0.1:5500/home
> myHistory.push('/about')
PUSH /about
url 變成:http://127.0.0.1:5500/about
> myHistory.back()
POP /home
url 變成:http://127.0.0.1:5500/home
> myHistory.replace('about')
REPLACE /about
url 變成:http://127.0.0.1:5500/about
> myHistory.back()
POP /public/test.html
url 變成:http://127.0.0.1:5500/public/test.html
這個流程其實就是 react 路由的基礎。
hash模式:
<script>
let hashHistory = window.HistoryLibrary.createHashHistory()
hashHistory.listen(({ location, action }) => {
console.log(action, location.pathname)
});
</script>
> hashHistory.push('/home')
PUSH /home
url 變為:http://127.0.0.1:5500/public/test.html#/home
Version 5 is used in React Router version 6 —— history
Tip:react router 用到了這個包,另外這個包的作者和 react-router、react-router-dom 是同一人。
路由模式
react 中有三種模式,本篇主要研究 history 和 hash 兩種模式。
官網-history:
- “browser history” - 在特定 DOM 上的實現,使用於支持 HTML5 history API 的 web 瀏覽器中
- “hash history” - 在特定 DOM 上的實現,使用於舊版本的 web 瀏覽器中
- “memory history” - 在內存中的 history 實現,使用於測試或者非 DOM 環境中,例如 React Native
環境准備
筆者使用的環境是 react 腳手架創建的項目。
Tip:詳細介紹請看 react 腳手架創建項目
打開 react-router 官網。

Tip:react 有三個版本,我們學習 web 版本 5。印記中文(深入挖掘國外前端新領域,為中國 Web 前端開發...)有 react-router 中文。
基礎使用
安裝 react 路由依賴包:
react-cli-demo> npm i react-router-dom@5
added 13 packages, and audited 1421 packages in 6s
169 packages are looking for funding
run `npm fund` for details
6 moderate severity vulnerabilities
To address all issues (including breaking changes), run:
npm audit fix --force
Run `npm audit` for details.
注:版本是5,倘若是版本 6,下面的代碼運行會報錯。
將 App.js 替換成下面代碼:
// src/App.js
import React from "react";
import {
BrowserRouter as Router,
Switch,
Route,
Link
} from "react-router-dom";
export default function BasicExample() {
return (
<Router>
<div>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/about">About</Link>
</li>
<li>
<Link to="/dashboard">Dashboard</Link>
</li>
</ul>
<hr />
<Switch>
<Route exact path="/">
<Home />
</Route>
<Route path="/about">
<About />
</Route>
<Route path="/dashboard">
<Dashboard />
</Route>
</Switch>
</div>
</Router>
);
}
// Home 組件
function Home() {
return (
<div>
<h2>Home</h2>
</div>
);
}
// About 組件
function About() {
return (
<div>
<h2>About</h2>
</div>
);
}
// Dashboard 組件
function Dashboard() {
return (
<div>
<h2>Dashboard</h2>
</div>
);
}
重啟服務器,頁面顯示:
· Home
· About
· Dashboard
________________________________
Home
注:本篇為了演示,所以將多個組件都放在一個文件中。
整個頁面分上下兩部分,上面是導航區,下面是內容區。
倘若點擊導航“About”,內容區顯示 About,瀏覽器 url 也會變化:
http://localhost:3000/
變成
http://localhost:3000/about
當我們點擊 <Link to="/about">About</Link>,則會匹配上 <Route path="/about">,於是 <About /> 組件顯示。
Tip:Link、exact、<Switch>、<Router>的作用?請接着看。
Link 和 NavLink
<Link to="/about/a">About</Link> 會被渲染成 <a href="/about">About</a>,即使點擊 About 導航,渲染的內容依舊不變。
一個特殊版本的 Link,當它與當前 URL 匹配時,為其渲染元素添加樣式屬性 —— 官網-<NavLink>
將 About 導航改成 NavLink:
<NavLink to="/about">About</NavLink>
初始時(即未選中)依舊渲染成 <a href="/about">About</a>,但點擊 About 導航后,渲染內容變成:
<a href="/about" aria-current="page" class="active">About</a>
所以我們可以給 .active 增加選中效果。
如果要修改默認選中時的 active 類名,可以使用 activeClassName 屬性。就像這樣:
<NavLink to="/about" activeClassName="z-selected">About</NavLink>
封裝 NavLink
- 版本1
function MyNavLink(props) {
return <NavLink to={props.to} activeClassName="z-selected">{props.children}</NavLink>
}
使用:
<MyNavLink to="/about" children="About" />
- 升級版
function MyNavLink(props) {
return <NavLink {...props} activeClassName="z-selected" />
}
當 React 元素為用戶自定義組件時,它會將 JSX 所接收的屬性(attributes)以及子組件(children)轉換為單個對象傳遞給組件,這個對象被稱之為 “props” —— react 官網
Router
使用 HTML5 歷史 API 記錄( pushState,replaceState 和 popstate 事件)的 <Router> 使您的UI與URL保持同步 —— 官網-BrowserRouter
假如將 BasicExample 組件中的 <Router> 刪除,瀏覽器控制台將報錯如下:
Uncaught Error: Invariant failed: You should not use <Link> outside a <Router>
未捕獲的錯誤:不變式失敗:您不應該在 <Router> 之外使用 <Link>
倘若將 <Switch> 外邊的 <Router> 刪除,瀏覽器控制台將報錯如下:
Uncaught Error: Invariant failed: You should not use <Switch> outside a <Router>
未捕獲的錯誤:不變量失敗:您不應該在 <Router> 之外使用 <Switch>
倘若將 <Route>(<Switch>在這里可以刪除) 外邊的 <Router> 刪除,瀏覽器控制台將報錯如下:
Uncaught Error: Invariant failed: You should not use <Route> outside a <Router>
未捕獲的錯誤:不變式失敗:您不應在 <Router> 之外使用 <Route>
倘若我們在 BasicExample 組件中使用兩個 <Router> 會發生什么?
export default function BasicExample() {
return (
<div>
<Router>
<ul>
<li>
<Link to="/">Home</Link>
</li>
...
</ul>
</Router>
<hr />
<Router>
<Switch>
<Route exact path="/">
<Home />
</Route>
...
</Switch>
</Router>
</div>
);
}
瀏覽器沒有任何報錯,點擊導航“About”,url正常變化,但內容區沒有跟着變。
Router 即路由器,Route 即線路,線路由路由器管理,上面用了兩個路由器,你管你的,我管我的,相互間沒有通信。
在 spug_web 中搜索 <Router 僅出現一次:
// spug_web/src/index.js
ReactDOM.render(
<Router history={history}>
<ConfigProvider locale={zhCN} getPopupContainer={() => document.fullscreenElement || document.body}>
<App/>
</ConfigProvider>
</Router>,
document.getElementById('root')
)
我們也依葫蘆畫瓢,將 <Router> 包裹 <App/>。
Switch
js 語法中就有 switch,類似於 if...else。我們對比有無 Switch 的兩種情況:
點擊 About 導航,請問內容區顯示什么?
// 沒有 Switch
export default function BasicExample() {
return (
<div>
<ul>
<li>
<Link to="/about">About</Link>
</li>
...
</ul>
<hr />
<Route path="/about">
<About />1
</Route>
<Route path="/about">
<About />2
</Route>
...
</div>
);
}
內容區顯示:
About
1
About
2
// 有 Switch
export default function BasicExample() {
return (
<div>
<ul>
<li>
<Link to="/about">About</Link>
</li>
...
</ul>
<hr />
<Switch>
<Route path="/about">
<About />1
</Route>
<Route path="/about">
<About />2
</Route>
...
</Switch>
</div>
);
}
內容區顯示:
About
1
渲染與該地址匹配的第一個子節點 <Route> 或者 <Redirect> —— 官網
Tip:既然只匹配第一個子節點,那么性能方面肯定會好些,因為不用在嘗試匹配后面的節點。
如果 URL 是 /about ,那么 <About>,<User> ,<NoMatch>將全部渲染,因為他們都與路徑匹配:
// from 官網
<Route exact path="/" component={Home}/>
<Route path="/about" component={About}/>
<Route path="/:user" component={User}/>
<Route component={NoMatch}/>
exact
exact 即精確的。首先做一個小練習:
點擊導航 About,下面兩個例子分別輸出什么,是否匹配?
export default function BasicExample() {
return (
<div>
<ul>
<li>
<Link to="/about">About</Link>
</li>
</ul>
<hr />
<Route path="/about/a">
<About />
</Route>
</div>
);
}
export default function BasicExample() {
return (
<div>
<ul>
<li>
<Link to="/about/a">About</Link>
</li>
</ul>
<hr />
<Route path="/about">
<About />
</Route>
</div>
);
}
第一個例子:內容區空白。未能匹配
第二個例子:內容區顯示”About“。匹配。
下面這段代碼呢?
export default function BasicExample() {
return (
<div>
<ul>
<li>
<Link to="/a/about/b">About</Link>
</li>
</ul>
<hr />
<Route path="/about">
<About />
</Route>
</div>
);
}
內容區空白。未能匹配。
總結:Link 可以多給,比如你要 /about,我給你傳 /about/a,但不能少給,而且順序不能亂,例如 /a/about/b 就不能匹配 /about
我們給第二個例子加上 exact,請問輸出什么?
export default function BasicExample() {
return (
<div>
<ul>
<li>
<Link to="/about/a">About</Link>
</li>
</ul>
<hr />
<Route exact path="/about">
<About />
</Route>
</div>
);
}
內容區空白。未能匹配。
如果為 true,則只有在路徑完全匹配 location.pathname 時才匹配 —— 官網-exact: bool
注:只有需要的時候才開啟精確匹配,也就是說頁面正常,就不要去開啟它。
Redirect
渲染 <Redirect> 將使導航到一個新的地址。這個新的地址會覆蓋 history 棧中的當前地址,類似服務器端(HTTP 3xx)的重定向 —— 官網-<Redirect>
下面我們用 <Redirect> 解決一個問題:
首先看下面這個例子:
export default function BasicExample() {
return (
<div>
<ul>
<li>
<Link to="/about">About</Link>
</li>
<li>
<Link to="/dashboard">Dashboard</Link>
</li>
</ul>
<hr />
<Switch>
<Route path="/about">
<About />
</Route>
<Route path="/dashboard">
<Dashboard />
</Route>
</Switch>
</div>
);
}
第一次來到網站(http://localhost:3000/),內容區是空白的,因為未能匹配任何 <Route>。
現在需求:進入網站,默認顯示 <Dashboard />。
只需要增加 2 行代碼:
import {
+ Redirect,
...
} from "react-router-dom";
export default function BasicExample() {
return (
<div>
...
<Switch>
<Route path="/about">
<About />
</Route>
<Route path="/dashboard">
<Dashboard />
</Route>
+ <Redirect to="/dashboard" />
</Switch>
</div>
);
}
瀏覽器輸入 http://localhost:3000/,由於前兩個 <Route> 未能匹配,最后就會重定向到 http://localhost:3000/dashboard。
replace
如果為 true,則單擊鏈接將替換歷史堆棧中的當前入口,而不是添加新入口 —— 官網-replace: bool
上面 BasicExample 組件,倘若我們依次點擊 About 組件、Dashboard 組件,接着點擊網頁左上角的返回(<-)按鈕,第一次會返回到 About 組件,再次點擊則會返回到 Home 組件。
如果我們給 Dashboard 組件加上 replace 屬性。就像這樣:
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/about">About</Link>
</li>
<li>
<Link to="/dashboard" replace>Dashboard</Link>
</li>
</ul>
依次點擊 About 組件、Dashboard 組件,然后第一次點擊返回按鈕,則回到 Home 組件。
因為點擊 Dashboard 導航時,不再是入棧操作(將 /dashboard 壓入棧中),而是替換操作(將棧中的 /about 替換成 /dashboard),再次點擊返回,就回到 /。
樣式丟失問題
通過一個示例演示問題:
首先在 index.html 增加樣式:
// public/index.html
+ <link rel="stylesheet" href="./css/index.css" />
// public/css/index.css
body{background-color: pink;}
修改 BasicExample 組件中 About 導航的路徑為多級路徑(/about 非多級路徑;/about/a 多級路徑):
// src/App.js
export default function BasicExample() {
return (
<Router>
<div>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/about/a/b">About</Link>
</li>
</ul>
<hr />
<Switch>
<Route exact path="/">
<Home />
</Route>
<Route path="/about/a/b">
<About />
</Route>
</Switch>
</div>
</Router>
);
}
開始測試:
啟動,http://localhost:3000/ 背景是粉色,樣式正常,點擊 ”About“導航,url 變成 http://localhost:3000/about/a/b,背景依舊是粉色,刷新頁面,粉色背景不見了,也就是樣式丟失了!
刷新的時候,發現樣式請求的地址和返回內容如下:
http://localhost:3000/about/a/css/index.css
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta name="description" content="Web site created using create-react-app" />
<link rel="apple-touch-icon" href="/logo192.png" />
<link rel="stylesheet" href="./css/index.css" />
<link rel="manifest" href="/manifest.json" />
<title>React App</title>
<script defer src="/static/js/bundle.js"></script></head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
</body>
</html>
注:請求不存在的資源,服務器會將 public/index.html 返回給你。例如請求:http://localhost:3000/a/b/c/d
我們放慢刷新這個動作:
- 刷新,給服務器發送
http://localhost:3000/about/a/b,沒有這個資源,所以服務器返回 index.html。 - 瀏覽器解析 index.html,遇到
<link rel="stylesheet" href="./css/index.css" />,需要加載當前目錄下的css/index.css資源,當前目錄是http://localhost:3000/about/a,於是請求http://localhost:3000/about/a/css/index.css - 由於存在對應資源,服務器再次返回 index.html,樣式也就丟失了
既然知道問題原因,只需要讓 css 資源路徑正常即可:
將
<link rel="stylesheet" href="./css/index.css" />
改成
<link rel="stylesheet" href="/css/index.css" />
或
<link rel="stylesheet" href="%PUBLIC_URL%/css/index.css" />
嵌套路由
嵌套路由也叫子路由。
將 BasicExample 組件中的 About 改造成嵌套路由。
首先看效果:
初始時 Home 導航選中:
· Home
· About
· Dashboard
________________________________
Home
點擊 About 導航:
· Home
· About
· Dashboard
________________________________
About
________________________________
· article1
· article2
點擊 article2 導航,顯示:
· Home
· About
· Dashboard
________________________________
About
________________________________
· article1
· article2
文章2...
嵌套路由相關代碼如下:
// About 組件
function About() {
return (
// 新增一個路由器 Router
<Router>
<div>
<h2>About</h2>
<hr />
<ul>
<li>
<Link to="/about/article1">article1</Link>
</li>
<li>
<Link to="/about/article2">article2</Link>
</li>
</ul>
<Switch>
<Route path="/about/article1">
文章1...
</Route>
<Route path="/about/article2">
文章2...
</Route>
</Switch>
</div>
</Router>
);
}
路由組件 vs 一般組件
路由組件和一般組件最大的一個區別是:props 中是否有路由相關方法。
這里有三個組件,請觀察每個組件的 props:
// src/App.js
import React from "react";
import {
Switch,
Route,
Link
} from "react-router-dom";
export default function BasicExample() {
return (
<div>
<Header />
<ul>
<li>
<Link to="/about">About</Link>
</li>
<li>
<Link to="/dashboard">Dashboard</Link>
</li>
</ul>
<hr />
<Switch>
<Route path="/about" component={About} />
<Route path="/dashboard">
<Dashboard name="pjl" />
</Route>
</Switch>
</div>
);
}
// Home 組件
function Header(props) {
console.log('Header props,', props)
return (
<h2>Header</h2>
);
}
// About 組件
function About(props) {
console.log('About props,', props)
return (
<div>
<h2>About</h2>
</div>
);
}
// Dashboard 組件
function Dashboard(props) {
console.log('Dashboard props,', props)
return (
<div>
<h2>Dashboard</h2>
</div>
);
}
初始 url 為:http://localhost:3000/,控制台輸出:Header props, {}
點擊 Dashboard 導航,控制台輸出:Dashboard props, {name: 'pjl'}
點擊 About 導航,控制台輸出:
About props, {history: {…}, location: {…}, match: {…}, staticContext: undefined}
三個組件只有 About 組件是路由組件,其用法不同於另外兩種組件:
// 通過 component 屬性指定組件
<Route path="/about" component={About} />
<Dashboard name="pjl" />
<Header />
Tip:路由組件中的 history、location、match 屬性,下文都會講到。
pages/components 目錄
有人說路由組件和一般組件從項目結構上可以區分,比如將路由組件放在 src/pages 文件夾中,一般組件放在 src/components 中。
spug_web 中有 src/pages 和 src/components 目錄,是否就是根據一般組件和路由組件進行區分?請看截取的代碼片段:
首先是 src/routes.js,猜測與路由相關:
// src/routes.js
import HomeIndex from './pages/home';
import DashboardIndex from './pages/dashboard';
import HostIndex from './pages/host';
import ExecTask from './pages/exec/task';
import ExecTemplate from './pages/exec/template';
import DeployApp from './pages/deploy/app';
import DeployRepository from './pages/deploy/repository';
import DeployRequest from './pages/deploy/request';
import ScheduleIndex from './pages/schedule';
import ConfigEnvironment from './pages/config/environment';
import ConfigService from './pages/config/service';
import ConfigApp from './pages/config/app';
import ConfigSetting from './pages/config/setting';
import MonitorIndex from './pages/monitor';
import AlarmIndex from './pages/alarm/alarm';
import AlarmGroup from './pages/alarm/group';
import AlarmContact from './pages/alarm/contact';
import SystemAccount from './pages/system/account';
import SystemRole from './pages/system/role';
import SystemSetting from './pages/system/setting';
import WelcomeIndex from './pages/welcome/index';
import WelcomeInfo from './pages/welcome/info';
引入的都是 pages 中的組件。
src/routes.js 又被 src\layout\index.js 引用:
// src/layout/index.js
import routes from '../routes';
// initRoutes 的實參 routes 就是上面導入的 routes
function initRoutes(Routes, routes) {
for (let route of routes) {
if (route.component) {
if (!route.auth || hasPermission(route.auth)) {
// 通過 component 屬性指定組件
Routes.push(<Route exact key={route.path} path={route.path} component={route.component}/>)
}
} else if (route.child) {
initRoutes(Routes, route.child)
}
}
}
...
至此,初步判斷:spug_web 中的 pages 目錄和 components 目錄就是根據一般組件和路由組件進行區分的。
給路由組件傳遞參數
給路由組件傳遞參數有三種方式。
下面通過這三種方式實現同一個功能:給路由組件 About 傳遞 name 和 age 兩個參數。
params 方式
export default function BasicExample() {
return (
<div>
<ul>
<li>
<Link to="/about/pjl/18">About</Link>
</li>
</ul>
<hr />
<Switch>
<Route path="/about/:name/:age" component={About}>
</Route>
</Switch>
</div>
);
}
// About 組件
function About(props) {
// {history: {…}, location: {…}, match: {…}, staticContext: undefined}
console.log(props)
// {name: 'pjl', age: '18'}
console.log(props.match.params)
return (
<div>
<h2>About</h2>
</div>
);
}
點擊 About 導航組件,控制台輸出:
{history: {…}, location: {…}, match: {…}, staticContext: undefined}
// 接收兩個參數
{name: 'pjl', age: '18'}
一個 match 對象中包涵了有關如何匹配 URL 的信息 —— 官網-match
search 方式
以 search 方式重寫 params 傳遞參數的例子:
export default function BasicExample() {
return (
<div>
<ul>
<li>
<Link to="/about/?name=pjl&age=18">About</Link>
</li>
</ul>
<hr />
<Switch>
<Route path="/about" component={About}>
</Route>
</Switch>
</div>
);
}
// About 組件
function About(props) {
// ?name=pjl&age=18
console.log(props.location.search)
var searchParams = new URLSearchParams(props.location.search)
const params = {}
for (const [key, value] of searchParams) {
params[key] = value
}
// params: {name: 'pjl', age: '18'}
console.log('params: ', params);
return (
<div>
<h2>About</h2>
</div>
);
}
需要自己將接收到的數據(例如 ?name=pjl&age=18)處理一下。
Tip:params 和 search 傳參,在地址欄中都能看見。例如 search:http://localhost:3000/about/?name=pjl&age=18。刷新頁面參數都不會丟失。
state 方式
注:與組件中的 state 沒有任何關系
export default function BasicExample() {
return (
<div>
<ul>
<li>
<Link to={{ pathname: '/about', state: { name: 'pjl', age: 18 } }}>About</Link>
</li>
</ul>
<hr />
<Switch>
<Route path="/about" component={About}>
</Route>
</Switch>
</div>
);
}
// About 組件
function About(props) {
// {name: 'pjl', age: 18}
console.log(props.location.state)
return (
<div>
<h2>About</h2>
</div>
);
}
有兩個特點:
- 所傳參數不會再 url 中體現。比如這里仍然是
http://localhost:3000/about - 強制刷新 url,所傳參數也不會消失。
- 筆者嘗試關閉瀏覽器,再次輸出
http://localhost:3000/about,控制台輸出undefined
- 筆者嘗試關閉瀏覽器,再次輸出
Tip:props.location === props.history.location 為 true
HashRouter 刷新會導致 state 參數丟失
HashRouter 模式下,刷新(非強刷)頁面會造成 state 參數的丟失。
將 App.js 中的 BrowserRouter 切換成 HashRouter 進行自測即可。
編程式導航 history
比如過3秒需要自動跳轉,這時就可以使用編程式導航。用法類似 History API。不過這里我們操作的是 props.history。
運行下面這個熟悉的例子,將會把 props.history 導出給 window.aHistory,我們直接在控制台中操作 aHistory:
// src/App.js
export default function BasicExample() {
return (
<div>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/about">About</Link>
</li>
<li>
<Link to="/dashboard">Dashboard</Link>
</li>
</ul>
<hr />
<Switch>
<Route exact path="/" component={Home} />
<Route path="/about" component={About} />
<Route path="/dashboard" component={Dashboard} />
</Switch>
</div>
);
}
// Home 組件
function Home(props) {
// 將 history 導出,用於測試
window.aHistory = props.history
return (
<div>
<h2>Home</h2>
</div>
);
}
// About 組件
function About() {
return (
<div>
<h2>About</h2>
</div>
);
}
// Dashboard 組件
function Dashboard() {
return (
<div>
<h2>Dashboard</h2>
</div>
);
}
瀏覽器 url 是 http://localhost:3000/,頁面內容如下:
· Home
· About
· Dashboard
________________________________
Home
測試開始:
> aHistory.push('/about')
url:http://localhost:3000/about
> aHistory.push('/dashboard')
url: http://localhost:3000/dashboard
> aHistory.goBack()
url: http://localhost:3000/about
// 等於 aHistory.goBack()
> aHistory.go(-1)
url: http://localhost:3000/
一般組件中使用編程式導航
一般組件中沒有 history,如果需要使用編程式導航,可以借助 withRouter 將一般組件處理一下即可。請看示例:
import React from "react";
import {
Switch,
Route,
withRouter,
Link
} from "react-router-dom";
export default function BasicExample() {
return (
<div>
<ul>
<li>
<Link to="/about">About</Link>
</li>
<li>
<Link to="/new-about">NewAbout</Link>
</li>
</ul>
<hr />
<Switch>
<Route path="/about">
<About />
</Route>
<Route path="/new-about">
<NewAbout />
</Route>
</Switch>
</div>
);
}
// About 組件
function About(props) {
console.log(props)
return (
<div>
<h2>About</h2>
</div>
);
}
var NewAbout = withRouter(About)
頁面顯示:
About
NewAbout
________________________________
依次點擊 About 導航、NewAbout 導航,控制台輸出:
{}
{history: {…}, location: {…}, match: {…}, staticContext: undefined}
其他章節請看:
