1. React Router的理解
React的路由根據(jù)項(xiàng)目的不同使用不同的路由庫,web應(yīng)用主要使用react-router和react-router-dom
react-router和react-router-dom的區(qū)別
-
react-rotuer核心庫,提供了一些核心的api,但是沒有提供dom操作進(jìn)行跳轉(zhuǎn)的api -
react-router-dom擴(kuò)展了核心庫,提供了一些操作DOM的api, - web應(yīng)用正常使用
react-router-dom就可以了, 因?yàn)樗约和瑯右蕾?code>react-router
2. 路由組件認(rèn)識(shí)
2.1 路由組件的認(rèn)識(shí)
在react中和vue不同的是,路由不是配置的文件,而是組件, 正常的組件嵌套使用
在React router中通常使用的組件有三種
- 路由器組件: 如BrowserRouter(history模式) 和 HashRouter(hash模式)
- 路由匹配組件: Route 和 Switch 組件
- 導(dǎo)航組件: Link 和 NavLink 組件
2.2. 相關(guān)API
<BrowserRouter> // 路由器組件
<HashRouter> // 路由器組件
<Route> // 顯示路由組件,嵌套在路由器組件中
<Switch> // 路由切換組件,如果配置成功多個(gè)路由也只會(huì)顯示第一個(gè)
<Link> // 路由導(dǎo)航組件
<NavLink> // 路由導(dǎo)航組件
<Redirect> // 路由重定向組件
3. 路由組件的使用
3.1 下載路由組件庫
$ npm install react-router-dom --save
## or
$ yarn add react-router-dom
3.2 路由器組件的使用
3.2.1 路由器組件說明:
- 每一個(gè)React Router應(yīng)用程序的核心都應(yīng)該是路由器組件
-
react-router-dom提供了BrowserRouter和HashRouter -
BrowserRouter采用常規(guī)路徑顯示方式的history路由顯示模式 -
HashRouter采用錨點(diǎn)顯示的hash路由顯示模式
3.2.2 BrowserRouter組件的使用
基本使用
采用history路由模式顯示路由
示例代碼:
// 導(dǎo)入路由器
import {BrowserRouter} from "react-router-dom"
// 使用路由器組件嵌套根組件APP
ReactDOM.render(
<BrowserRouter>
<App />
</BrowserRouter>,
document.getElementById('root')
);
為什么使用BrowserRouter嵌套根組件APP呢?
其實(shí)沒有說一定要嵌套APP根組件, 只是導(dǎo)航組件和路由組件必須嵌套的路由器組件中才會(huì)有效,否則就會(huì)報(bào)錯(cuò)
因此只要在你是用的導(dǎo)航組件和路由組件外嵌套即可, 嵌套根組件表示整個(gè)應(yīng)用任何位置都可以是使用路由組件
BrowserRouter路由器采用history前端路由模式, 因此在路徑顯示上沒有#
如下:
http://localhost:3000/goods
3.2.3 HashRouter組件的使用
HashRouter采用hash模式的前端路由, 以此會(huì)出現(xiàn)#/home
示例代碼:
// 導(dǎo)入路由器
import {HashRouter} from "react-router-dom"
// 使用路由器組件嵌套根組件APP
ReactDOM.render(
<HashRouter>
<App />
</HashRouter>,
document.getElementById('root')
);
路徑顯示結(jié)果:
http://localhost:3000/#/goods
3.2.4 路由器的別名使用
有的時(shí)候會(huì)將路由器組件在使用import導(dǎo)入是修改別名
示例代碼如下
// 將HashRouter 路由器組件修改為別名Router使用
import {HashRouter as Router} from "react-router-dom"
// 使用路由器組件的別名
ReactDOM.render(
<Router>
<App />
</Router>,
document.getElementById('root')
);
3.3 路由匹配組件的使用
3.3.1 路由匹配組件Route的使用
Route組件用來控制路徑對(duì)應(yīng)顯示的組件
說明:
-
Route組件基本的兩個(gè)屬性,一個(gè)是path,一個(gè)是component -
path屬性表示用來匹配路徑,黨路徑匹配成功后展示component的內(nèi)容 -
component屬性值是將來用于展示的組件
示例代碼如下:
import {Route, Link} from 'react-router-dom'
// 導(dǎo)入組件
import Home from "./components/Home"
import Goods from "./components/Goods"
import About from "./components/About"
// App組件
function App() {
return (
<div className="App">
{/*
Route路由展示組件
當(dāng)path的值和路徑匹配成功后顯示component對(duì)應(yīng)的組件
*/}
<Route path="/home" component={Home}/>
<Route path="/goods" component={Goods}/>
<Route path="/about" component={About}/>
</div>
);
}
示例代碼說明:
- 上面的示例代碼,在默認(rèn)打開是不顯示任何組件內(nèi)容,
- 默認(rèn)打開的路徑為
/所以Route中的路徑都匹配不成功 - 如果希望
/路由對(duì)應(yīng)的顯示內(nèi)容也為首頁, 就可能會(huì)如下寫法
示例代碼
import {Route, Link} from 'react-router-dom'
import Home from "./components/Home"
import Goods from "./components/Goods"
import About from "./components/About"
function App() {
return (
<div className="App">
<Route path="/home" component={Home}/>
<Route path="/goods" component={Goods}/>
<Route path="/about" component={About}/>
<Route path="/" component={Home}/>
</div>
);
}
示例代碼說明:
- 示例的本意是希望
/home和/路徑都展示首頁組件,/表示默認(rèn)打開顯示首頁 - 但是示例真實(shí)的情況是,無論
/home,/goods,/about路徑,最后一個(gè)/Route都會(huì)展示 - 這樣就導(dǎo)致了頁面會(huì)同時(shí)渲染兩個(gè)組件,
3.3.2 Switch組件
Switch組件說明:
- Switch組件用于包裹Route組件, 表示只會(huì)渲染第一個(gè)與路徑配置成功的Route組件對(duì)應(yīng)的內(nèi)容
- 如果有兩個(gè)組件都匹配路徑都成功,也只會(huì)顯示第一個(gè),
- 或者顯示Redirect重定向組件內(nèi)容
- 也就是說路徑只會(huì)匹配到第一個(gè)成功的Route就不會(huì)在下匹配其他Route組件了,
- 如果不使用Switch組件,則會(huì)將所有Route組件都匹配一下,所有匹配成功的組件都會(huì)展示
示例代碼如下
import {Route, Link,Switch} from 'react-router-dom'
import Home from "./components/Home"
import Goods from "./components/Goods"
import About from "./components/About"
function App() {
return (
<div className="App">
<Switch>
<Route path="/home" component={Home}/>
<Route path="/goods" component={Goods}/>
<Route path="/about" component={About}/>
<Route path="/" component={Home}/>
</Switch>
</div>
);
}
示例說明:
- 這樣就解決了之前存在的問題
- 當(dāng)路由為
/時(shí)匹配最后一個(gè)Route,因此展示首頁 - 如果當(dāng)路由匹配到
/goods,展示商品頁,此時(shí)會(huì)中斷匹配, 也就不會(huì)匹配到/,此時(shí)也不會(huì)再次展示一個(gè)首頁組件
3.4 導(dǎo)航組件
3.4.1 導(dǎo)航組件說明:
- 導(dǎo)航組件的作用是用來點(diǎn)擊跳轉(zhuǎn)路由,為
Link和NavLink -
Link組件和NavLink組件的區(qū)別在于時(shí)候會(huì)添加額外的類名 -
Link組件在跳轉(zhuǎn)路由時(shí),當(dāng)前活躍的導(dǎo)航不會(huì)添加任何類名 -
NavLink跳轉(zhuǎn)路由,會(huì)給當(dāng)前活躍的導(dǎo)航添加額外的類名,可以利用類名添加不同的樣式
3.4.2 Link組件的使用
Link組件有一個(gè)to屬性, 有來指定跳轉(zhuǎn)到那個(gè)路由
示例代碼如下:
import {Route, Link,Switch} from 'react-router-dom'
import Home from "./components/Home"
import Goods from "./components/Goods"
import About from "./components/About"
function App() {
return (
<div className="App">
<Link to="/home">首頁</Link>
<Link to="/goods">商品頁</Link>
<Link to="/about">關(guān)于頁</Link>
<Switch>
<Route path="/home" component={Home}/>
<Route path="/goods" component={Goods}/>
<Route path="/about" component={About}/>
<Route path="/" component={Home}/>
</Switch>
</div>
);
}
示例說明:
-
Link標(biāo)簽會(huì)被編譯為a標(biāo)簽 -
to屬性表示當(dāng)你點(diǎn)擊時(shí),跳轉(zhuǎn)到那個(gè)路由上 - 但是不會(huì)添加任何額外的類名
控制臺(tái)Elements里展示的內(nèi)容
<div class="App">
<a href="#/home">首頁</a>
<a href="#/goods">商品頁</a>
<a href="#/about">關(guān)于頁</a>
<div>這是首頁</div>
</div>
因此沒發(fā)確定當(dāng)前那個(gè)導(dǎo)航對(duì)應(yīng)的路由是活躍狀態(tài)
3.4.3 NavLink 組件的使用
NavLink會(huì)給當(dāng)前活躍的路徑導(dǎo)航添加額外的類名, 利用添加給導(dǎo)航添加不同的樣式
因此NavLink組件使用相對(duì)較多
示例代碼:
import {Route, NavLink,Switch} from 'react-router-dom'
import Home from "./components/Home"
import Goods from "./components/Goods"
import About from "./components/About"
function App() {
return (
<div className="App">
<NavLink to="/home">首頁</NavLink>
<NavLink to="/goods">商品頁</NavLink>
<NavLink to="/about">關(guān)于頁</NavLink>
<Switch>
<Route path="/home" component={Home}/>
<Route path="/goods" component={Goods}/>
<Route path="/about" component={About}/>
<Route path="/" component={Home}/>
</Switch>
</div>
);
}
示例顯示后的Elements結(jié)果
<div class="App">
<a href="#/home">首頁</a>
<a href="#/goods" aria-current="page" class="active">商品頁</a>
<a href="#/about">關(guān)于頁</a><
div>商品頁面</div>
</div>
此時(shí)會(huì)發(fā)現(xiàn),當(dāng)前展示的是商品頁面, 對(duì)應(yīng)的導(dǎo)航會(huì)有一個(gè)額外的類名activ
因此可以利用active給當(dāng)前顯示的導(dǎo)航添加不同的樣式
.active{
color:red;
}
3.5 路由重定向組件的使用
路由重定向 Redirect 組件使用說明
-
Redirect組件可以在所有路由都匹配不成功后,默認(rèn)跳轉(zhuǎn)展示的內(nèi)容,如訪問的路由不存在,展示首頁 -
Redirect組件也可以在路由匹配成功后,驗(yàn)證權(quán)限, 不足的跳轉(zhuǎn)指定路由, 如登錄賬號(hào)不存在跳轉(zhuǎn)注冊(cè)
示例代碼:
import {Route, NavLink,Switch,Redirect} from 'react-router-dom'
import Home from "./components/Home"
import Goods from "./components/Goods"
import About from "./components/About"
function App() {
return (
<div className="App">
<NavLink to="/home">首頁</NavLink>
<NavLink to="/goods">商品頁</NavLink>
<NavLink to="/about">關(guān)于頁</NavLink>
<Switch>
<Route path="/home" component={Home}/>
<Route path="/goods" component={Goods}/>
<Route path="/about" component={About}/>
<Route path="/" component={Home}/>
{/* 使用路由重定向, 當(dāng)路由匹配不成功時(shí),顯示首頁 */}
<Redirect to="/home" />
</Switch>
</div>
);
}
3.6 withRouter組件的使用
3.6.1 withRouter組建了解
- withRouter為高階組件,其實(shí)就是一個(gè)函數(shù),參數(shù)是一個(gè)組件, 返回值也是一個(gè)組件
- 正常的路由組件都能在props屬性接受和路由有關(guān)的
match,location,history對(duì)象 - 如果是非路由組件不能在props屬性中獲取這些路由對(duì)象,如果需要在非路由組件中使用路由對(duì)象內(nèi)容
- 就需要給非路由組件嵌套一個(gè)
WitchRouter高級(jí)組件,
因?yàn)?code>WitchRouter組件就是為了讓非路由組件也能訪問路由對(duì)象的高階組件
3.6.2 未使用withRouter
非路由組件中獲取props
export default class Header extends Component {
render() {
console.log(this.props);
/*
打印結(jié)果:
{}
*/
return (
<h2>應(yīng)用的頭部</h2>
);
}
}
路由組件中獲取props
export default class Home extends Component {
render() {
console.log(this.props);
/*
打印結(jié)果:
{
history: {...},
location:{...},
match:{...},
}
*/
return (
<div>
這是首頁
</div>
);
}
}
3.6.3 使用withRouter
使用withRouter執(zhí)行,傳入非路由組件
import React, { Component } from 'react';
// 引入高級(jí)組件
import { withRouter } from 'react-router-dom'
class Header extends Component {
render() {
console.log(this.props);
/*
打印結(jié)果:
{
history: {...},
location:{...},
match:{...},
}
*/
return (
<h2>應(yīng)用的頭部</h2>
);
}
}
/*
使用高級(jí)組件, withRouter的參數(shù)是Header組件,
返回一個(gè)處理后的組件
*/
export default withRouter(Header)
此時(shí)非路由組建的props屬性中就可以獲取到路由組件才能獲取到的history,math,location對(duì)象