React路由介紹
現(xiàn)代的前端應(yīng)用大多數(shù)是SPA(單頁(yè)應(yīng)用程序),也就是只有一個(gè)HTML頁(yè)面的應(yīng)用程序。因?yàn)樗挠脩趔w驗(yàn)更好、對(duì)服務(wù)器壓力更小,所以更受歡迎。為了有效的使用單個(gè)頁(yè)面來(lái)管理多頁(yè)面的功能,前端路由應(yīng)運(yùn)而生。
- 前端路由功能:讓用戶從一個(gè)視圖(頁(yè)面)導(dǎo)航到另一個(gè)視圖(頁(yè)面)
- 前端路由是一套映射規(guī)則,在React中,是URL路徑與組件的對(duì)應(yīng)關(guān)系
- 使用React路由簡(jiǎn)單來(lái)說(shuō),就是配置路徑和組件
路由的基本使用
使用步驟
- 1.安裝:
yarn add react-router-dom
如果沒(méi)有安裝yarn工具的,需要先全局安裝一下yarn:npm install -g yarn - 2.導(dǎo)入路由的三個(gè)核心組件:
Router / Route / Link
import {BrowserRouter as Router, Route, Link} from 'react-router-dom'
- 使用 Router 組件包裹整個(gè)應(yīng)用(重要)
<Router>
<div className="App">
// … 省略頁(yè)面內(nèi)容
</div>
</Router>
- 使用 Link 組件作為導(dǎo)航菜單(路由入口)
<Link to="/first">頁(yè)面一</Link>
- 使用 Route 組件配置路由規(guī)則和要展示的組件(路由出口)
const First = () => <p>頁(yè)面一的頁(yè)面內(nèi)容</p>
<Router>
<div className="App">
<Link to="/first">頁(yè)面一</Link>
<Route path="/first" component={First}></Route>
</div>
</Router>
常用組件說(shuō)明
-
Router組件:包裹整個(gè)應(yīng)用,一個(gè)React應(yīng)用只需要使用一次
- 兩種常用的Router: HashRouter和BrowserRouter
-
HashRouter: 使用URL的哈希值實(shí)現(xiàn) (localhost:3000/#/first) - 推薦
BrowserRouter:使用H5的history API實(shí)現(xiàn)(localhost3000/first)
-
Link組件:用于指定導(dǎo)航鏈接(a標(biāo)簽)
- 最終Link會(huì)編譯成a標(biāo)簽,而to屬性會(huì)被編譯成 a標(biāo)簽的href屬性
<Link to="/first">頁(yè)面一</Link>
-
Route組件:指定路由展示組件相關(guān)信息
- path屬性:路由規(guī)則,這里需要跟Link組件里面to屬性的值一致
- component屬性:展示的組件
- Route寫(xiě)在哪,渲染出來(lái)的組件就在哪
<Route path="/first" component={First}></Route>
路由的執(zhí)行過(guò)程
1.當(dāng)我們點(diǎn)擊Link組件的時(shí)候,修改了瀏覽器地址欄中的url
2.React路由監(jiān)聽(tīng)地址欄url的變化
-
3.React路由內(nèi)部遍歷所有的Route組件,拿著Route里面path規(guī)則與pathname進(jìn)行匹配
image.png - 當(dāng)路由規(guī)則(path)能夠匹配地址欄中的 pathname 時(shí),就展示該 Route 組件的內(nèi)容。
編程式導(dǎo)航
- 場(chǎng)景:點(diǎn)擊登陸按鈕,登陸成功后,通過(guò)代碼跳轉(zhuǎn)到后臺(tái)首頁(yè),如何實(shí)現(xiàn)?
- 編程式導(dǎo)航:通過(guò)JS代碼來(lái)實(shí)現(xiàn)頁(yè)面跳轉(zhuǎn)
- history是React路由提供的,用于獲取瀏覽器歷史記錄的相關(guān)信息
- push(path):跳轉(zhuǎn)到某個(gè)頁(yè)面,參數(shù)path表示要跳轉(zhuǎn)的路徑
- go(n):前進(jìn)或后退功能,參數(shù)n表示前進(jìn)或后退頁(yè)面數(shù)量
import React from 'react'
import ReactDOM from 'react-dom'
/*
編程式導(dǎo)航
*/
import { BrowserRouter as Router, Route, Link } from 'react-router-dom'
class Login extends React.Component {
handleLogin = () => {
// 使用編程式導(dǎo)航實(shí)現(xiàn)路由跳轉(zhuǎn)
// ...省略其他功能代碼
this.props.history.push('/home')
}
render() {
return (
<div>
<p>登錄頁(yè)面:</p>
<button onClick={this.handleLogin}>登錄</button>
</div>
)
}
}
const Home = props => {
const handleBack = () => {
// go(-1) 表示返回上一個(gè)頁(yè)面
props.history.go(-1)
}
return (
<div>
<h2>我是后臺(tái)首頁(yè)</h2>
<button onClick={handleBack}>返回登錄頁(yè)面按鈕</button>
</div>
)
}
const App = () => (
<Router>
<div>
<h1>編程式導(dǎo)航:</h1>
<Link to="/login">去登錄頁(yè)面</Link>
<Route path="/login" component={Login} />
<Route path="/home" component={Home} />
</div>
</Router>
)
ReactDOM.render(<App />, document.getElementById('root'))
默認(rèn)路由
- 現(xiàn)在的路由都是通過(guò)點(diǎn)擊導(dǎo)航菜單后展示的,如果進(jìn)入頁(yè)面的時(shí)候就主動(dòng)觸發(fā)路由呢
- 默認(rèn)路由:表示進(jìn)入頁(yè)面時(shí)就會(huì)匹配的路由
- 默認(rèn)路由:只需要把path設(shè)置為
'/'
<Route path="/" component={Home} />
匹配模式
1.模糊匹配模式
- 當(dāng)Link組件的to屬性值為 '/login' 時(shí)候,為什么默認(rèn)路由也被匹配成功?
- 默認(rèn)情況下,React路由是模糊匹配模式
- 模糊匹配規(guī)則:只要pathname以path開(kāi)頭就會(huì)匹配成功
path 代表Route組件的path屬性
pathname 代表Link組件的to屬性(也就是 location.pathname)

image.png
精準(zhǔn)匹配
- 默認(rèn)路由認(rèn)可情況下都會(huì)展示,如果避免這種問(wèn)題?
- 給Route組件添加exact屬性,讓其變?yōu)?strong>精準(zhǔn)匹配模式
- 精確匹配:只有當(dāng)path和pathname完全匹配時(shí)才會(huì)展示改路由
// 此時(shí),該組件只能匹配 pathname=“/” 這一種情況
<Route exact path="/" component=... />
案例:
import React from 'react'
import ReactDOM from 'react-dom'
/*
模糊匹配模式
*/
import { BrowserRouter as Router, Route, Link } from 'react-router-dom'
const Home = () => <p>進(jìn)入頁(yè)面的時(shí)候,你能看到我嗎?</p>
const Login = () => <p>我是Login組件的內(nèi)容</p>
const App = () => (
<Router>
<div>
<h1>默認(rèn)路由</h1>
<ul>
<li>
<Link to="/">首頁(yè)</Link>
</li>
<li>
<Link to="/login">登錄頁(yè)面</Link>
</li>
</ul>
{/* 默認(rèn)路由,添加 exact 屬性,就會(huì)讓當(dāng)前路由變?yōu)榫_匹配 */}
<Route exact path="/" component={Home} />
<Route path="/login" component={Login} />
</div>
</Router>
)
ReactDOM.render(<App />, document.getElementById('root'))
