目录
安装时,我们可以选择react-router-dom, react-router会包含一些react-native的内容,web开发并不需要;
npm install react-router-dom
1.react-router的两种模式
-
BrowserRouter:使用history模式
-
HashRouter:使用hash模式
配置路由模式
<React.StrictMode>
<BrowserRouter>
<App />
</BrowserRouter>
</React.StrictMode>
2.路由映射配置
-
Routes:包裹所有的Route,在其中匹配一个路由,Router5.x使用的是Switch组件
-
Route:Route用于路径的匹配
-
path属性:用于设置匹配到的路径;
-
element属性:设置匹配到路径后,渲染的组件;Router5.x使用的是component属性
-
exact:精准匹配,只有精准匹配到完全一致的路径,才会渲染对应的组件;Router6.x不再支持该属性
-
import { Route } from 'react-router-dom'
import Login from '../pages/Login'
import Home from '../pages/Home'
<Route path='/login' element={<Login/>}></Route>
<Route path='/home' element={<Home/>}></Route>
3.路由配置和跳转
-
Link:通常路径的跳转是使用Link组件,最终会被渲染成a元素。to属性:Link中最重要的属性,用于设置跳转到的路径
import { Link } from 'react-router-dom'
<Link to='/home'>首页</Link>
<Link to='/login'>登录</Link>
4.Navigate导航
作用:Navigate用于路由的重定向,当这个组件出现时,就会执行跳转到对应的to路径中:
设置重定向:
<Route path='/' element={<Navigate to='/home'/>}></Route>
设置路径不匹配,调整默认页面:
<Route path='*' element={<NotFound/>}></Route>
5.手动跳转路由
除了使用Link和NavLink进行组件跳转,我们还可以通过js代码来进行跳转,但是在Router6.x版本后,useNavigate()已经迁移到hook上了,而且hook只能在函数式组件上使用,那我们需要封装一个高阶组件来增强我们需要用到useNavigate()的组件,这个组件通过useNavigate()返回的对象进行路由跳转。
import { useNavigate } from "react-router-dom"
export function withRouter(WrapperComponent) {
return props => {
const navigate = useNavigate()
return <WrapperComponent {...props} router={{ navigate }} />
}
}
6.路由参数传递
路由参数传递有两种方式:
-
动态路由的方式
动态路由映射:
<Route path='/detail/:id' element={<Detail/>}></Route>
动态路由的跳转:
navigateToDetail(item) {
const { navigate } = this.props.router
navigate('/detail/' + item.id)
}
动态路由参数获取(useParams函数):
import { useNavigate, useParams } from "react-router-dom"
export function withRouter(WrapperComponent) {
return props => {
const navigate = useNavigate()
const params = useParams()
return <WrapperComponent {...props} router={{ navigate, params }} />
}
}
import React, { PureComponent } from 'react'
import { withRouter } from '../hoc'
export class Detail extends PureComponent {
render() {
const { params } = this.props.router
return (
<div>
<h2>Detail</h2>
<div>id: {params.id}</div>
</div>
)
}
}
export default withRouter(Detail)
-
search传递参数
<Route path='/user' element={<User/>}></Route>
<Link to='/user?name=kk&age=18'>用户</Link>
使用useLocation和useSearchParams函数:
import { useNavigate, useParams, useLocation, useSearchParams, useRoutes } from "react-router-dom"
export function withRouter(WrapperComponent) {
return props => {
const navigate = useNavigate()
const params = useParams()
const location = useLocation()
const [ searchParams ] = useSearchParams()
const query = Object.fromEntries(searchParams)
return <WrapperComponent {...props} router={{ navigate, params, location, query, useRoutes }} />
}
}
使用useLocation返回的值:
使用useSearchParams返回一个数组:
拿到数组第一个值,也就是一个可迭代对象:
可迭代对象转化为普通数组:
7.路由的配置文件
目前我们所有的路由都是通过Route组件来定义的,如果我们想像vue那样有一个配置文件来配置路由,其实react也可以单独配置一个路由文件。
步骤:
const routes = [
{
path: '/',
element: <Navigate to='/home'/>
},
{
path: '/login',
element: <Login/>
},
{
path: '/home',
element: <Home/>,
children: [
{
path: '/home',
element: <Navigate to='/home/recommend'/>
},
{
path: '/home/recommend',
element: <Recommend/>
},
{
path: '/home/ranking',
element: <Ranking/>
},
{
path: '/home/songmenu',
element: <HomeSongMenu/>
},
]
},
]
在react-router6.x后,我们使用useRoutes函数来完成配置,在react-router6.x之前,我们是通过react-router-config完成。
import React from 'react'
import { Link, useRoutes } from 'react-router-dom'
import routes from './router'
export function App() {
return (
<div>
<div className='header'>
<h1>header</h1>
<Link to='/home'>首页</Link>
<Link to='/login'>登录</Link>
</div>
<div className='content'>
{
useRoutes(routes)
}
</div>
<div className='foot'>
<h1>foot</h1>
</div>
</div>
)
}
export default App
配置路由懒加载(调用React.lazy函数,这个函数需要接受一个回调函数,这个回调函数且要返回一个promise):
// 路由懒加载
const Home = React.lazy(() => import('../pages/Home'))
使用懒加载,还的使用Suspense进行包裹:
<React.Suspense fallback={ <h3>Loading</h3> }/>
<App />
<React.Suspense/>