安装 : npm install react-router-dom
定义路由规则
src/router/index.js
import React, { Component } from 'react'import { HashRouter as Router,Redirect,Route,Switch} from 'react-router-dom'import Films from '../views/Films' //...一堆组件引入function isAuth(){return localStorage.getItem("token")}export default class IndexRouter extends Component {render() {return (<Router>{this.props.children}<Switch><Route path="/films" component={Films} /><Route path="/cinemas" component={Cinemas} /><Route path="/center" component={Center} />{/* 默认路由 */}<Redirect from="/" to="/home" exact/>{/* 404 这个要放到最后(当匹配不到时) */}<Route component={NotFound}/></Switch></Router>)}}
Switch 渲染第一个匹配
- 通常情况下,path和component是一一对应的关系。
- Switch可以提高路由匹配效率(单一匹配)。react 默认会一直往下找Route匹配 , 添加了Switch则不会匹配下一个
/home```jsx import {Route ,Switch} from ‘react-router-dom’;
{/同时展示Home Test两个组件/}
{/只展示Home组件/}
<a name="Mxuip"></a>
### exact - 路由的严格匹配与模糊匹配
1.默认使用的是模糊匹配(简单记:【输入的路径】必须包含要【匹配的路径】,且顺序要一致)<br />2.开启严格匹配:`<Route exact path="/about" component={About}/>`<br />3.严格匹配不要随便开启,需要再开,有些时候开启会导致无法继续匹配二级路由
<a name="E2y0f"></a>
### Redirect(路由重定向)的使用
1. 访问[http://localhost:3000](http://localhost:3000/about) 会跳到 [http://localhost:3000/about](http://localhost:3000/about)
1. 访问不存在的也会调到[http://localhost:3000/about](http://localhost:3000/about)jsx
import {Route ,Redirect} from ‘react-router-dom’
{/
1.一般写在所有路由注册的最下方,当所有路由都无法匹配时,跳转到Redirect指定的路由
2.具体编码:
/}
<a name="TEhBv"></a>
## 导入路由
> app.js导入使用jsx
import React, { Component } from ‘react’
import Router from ‘./router/IndexRouter’
import Tabbar from ‘./components/Tabbar’
export default class App extends Component {
render() {
return (
<a name="l1zGU"></a>
## NavLink声明式导航
> Tabbar组件jsx
import { NavLink } from ‘react-router-dom’
{/ Navlink会被渲染为a标签/}
<a name="PkCuL"></a>
### 禁用Link
> 想要禁用Link,开发阶段使用 `BrowserRouter` 可以使用:jsx
xxx
> 但如果上线使用 `HashRouter` ,就会跳到404页面,因此需要补充:jsx
xxx
// App.less中补上:
a[disabled] {
pointer-events: none;
}
<a name="bsDqM"></a>
## 编程式路由导航jsx
//类组件
class Home extends Component{
this.props.history.push(/filmsorder)
}
//函数组件
function Center(props) {
props.history.push(/filmsorder)
}
//hooks函数组件
import {useHistory} from ‘react-router-dom’
function Center(props) {
const history =useHistory()
history.push(/filmsorder)
}
//其他路由方法
-this.prosp.history.push()
-this.prosp.history.replace()
-this.prosp.history.goBack() -后退
-this.prosp.history.goForward() -前进
-this.prosp.history.go() -参数n,可以是负数
<a name="xFQK2"></a>
## 嵌套路由
<a name="XZw9i"></a>
### 写法一
> 将嵌套路由写到父路由中jsx
import React, { Component } from ‘react’
import Nowplaying from ‘./films/Nowplaying’
import {NavLink, Redirect, Route, Switch} from ‘react-router-dom’
//Films的路由规则 已经定义过 <a name="E0Q5d"></a>
### 写法二
由写法一可延伸为以下写法 可以不用写到父组件中
> router/index.js 定义路由规则

> 父组件 这里是app组件, 利用this.props.children(react.creatElement将children渲染为标签中间的内容)
> 按照vue的话可以理解为一个<view-router>

<a name="r3XFv"></a>
## 路由传参
<a name="WJrDr"></a>
### 1. paramsjsx
{/ /detail/1111 定义规则 /}
/detail/${id})
//或<a name="fgjKj"></a>
### 2. queryjsx
<a name="m9tpW"></a>
### 3. statejsx
<a name="r5Kfj"></a>
## 路由拦截(守卫)
<a name="f2lYi"></a>
### 函数形式
> src/router/index.jsjsx
import React, { Component } from ‘react’
import { HashRouter as Router,Redirect,Route,Switch} from ‘react-router-dom’
//…一堆组件引入
//判断是否登录
function isAuth(){
return localStorage.getItem(“token”)
}
export default class IndexRouter extends Component {
render() {
return (
</Router>
)
} }
<a name="UDOc1"></a>
### 高阶组件形式
> components/AuthRoute/index.js
```jsx
// 1. 判断token是否存在
// 2. 如果存在 直接正常渲染
// 3. 如果不存在 重定向到登录路由
// 高阶组件:把一个组件当成另外一个组件的参数传入 然后通过一定的判断 返回新的组件
import { getToken } from '@/utils'
import { Navigate } from 'react-router-dom'
function AuthRoute ({ children }) {
const isToken = getToken()
if (isToken) {
return <>{children}</>
} else {
return <Navigate to="/login" replace />
}
}
// <AuthComponent> <Layout/> </AuthComponent>
// 登录:<><Layout/></>
// 非登录:<Navigate to="/login" replace />
export {
AuthRoute
}
src/router/index.js
import { AuthRoute } from './components/AuthRoute'
<Routes>
{/* 需要鉴权的路由 */}
<Route path="/" element={
<AuthRoute>
<Layout />
</AuthRoute>
}>
</Route>
{/* 不需要鉴权的路由 */}
<Route path='/login' element={<Login />} />
</Routes>
lazyLoad - 按需加载 -v16.6以上
run build时会单独生成js和css文件,点击路由导航时才会在newwork加载
import {lazy,Suspense} from 'react'<Suspense fallback={}>import React , {Component,lazy,Suspense} from 'react' //1.通过React的lazy函数配合import()函数动态加载路由组件 ===> 路由组件代码会被分开打包 const Login = lazy(()=>import('@/pages/Login')) //2.通过<Suspense>指定在加载得到路由打包文件前显示一个自定义loading界面 {/* <Suspense fallback={<Loading/>}> */} //可以导入一个Loading组件作为fallback <Suspense fallback={<h1>loading.....</h1>}> <Switch> <Route path="/xxx" component={Xxxx}/> <Redirect to="/login"/> </Switch> </Suspense>withRouter 将非路由组件转为路由组件
withRouter可以加工一般组件,让一般组件具备路由组件所特有的API
- withRouter的返回值是一个新组件 ```jsx import React, { Component } from ‘react’ import {withRouter} from ‘react-router-dom’
class Header extends Component { go = ()=>{ this.props.history.go(-2) }
render() {
console.log('Header组件收到的props是',this.props);
return (
<div className="page-header">
<button onClick={this.go}>go</button>
</div>
)
}
} //props 具有history是可以使用路由功能 export default withRouter(Header) ```
BrowserRouter与HashRouter的区别
1.底层原理不一样:
(1).BrowserRouter使用的是H5的history API,不兼容IE9及以下版本。
ps:this.props中的history是react封装的 不是H5中的
(2).HashRouter使用的是URL的哈希值。相当于锚点
不会发给服务器但又能形成历史记录,所以可以使用history的API实现前进后退。
2.path表现形式不一样
BrowserRouter的路径中没有#,例如:localhost:3000/demo/test
HashRouter的路径包含#,例如:localhost:3000/#/demo/test
3.刷新后对路由state参数的影响
(1).BrowserRouter没有任何影响,因为state保存在history对象中。
(2).HashRouter刷新后会导致路由state参数的丢失!!!
4.备注:HashRouter可以用于解决一些路径错误相关的问题。
