1. 改变了什么
- 推荐使用函数组件
- 使用Routes替换原来的Switch组件
- 使用Navigate组件替换原来的Redirect组件
- Route组件必须包裹在Routes组件里
- 路由规则是严格匹配,匹配成功就不向下继续匹配
- 定义路由规则匹配渲染组件语法改变
component/render/children => element={<名称 />}
- 新增了多个hook函数,useParams、useSearchParams、useNavigate、useRoutes等
2. 路由安装和定义路由规则
安装:
yarn add react-router-dom@6
使用:
-
在 src/index.js 文件中定义当前项目所使用的路由模式
import React from 'react' import ReactDOM from 'react-dom/client' import App from './App' // 定义当前项目的路由模式 import { BrowserRouter as Router } from 'react-router-dom' const root = ReactDOM.createRoot(document.getElementById('root')); root.render( <Router> <App /> </Router> );
-
在 src/App.jsx 组件中定义路由规则
import React from 'react' // 定义路由规则 import { Routes, Route, Link, NavLink, Navigate } from 'react-router-dom' // Route用来定义路由规则的,它一定要在Routes组件中包裹起来,否则报错 // 路由匹配成功后要渲染的组件 import Home from './views/Home' import About from './views/About' const App = () => { return ( <div> <Routes> <Route path='/' element={ <Home />} /> <Route path='/about' element={ <About />} /> </Routes> </div> ) } export default App
3. 声明式导航
import React from 'react'
// 定义路由规则
import {
Routes, Route, Link, NavLink, Navigate } from 'react-router-dom'
// Route用来定义路由规则的,它一定要在Routes组件中包裹起来,否则报错
// Link, NavLink 用于声明式导航,它们编译为html都为a标签,NavLink有激活样式
// 路由匹配成功后要渲染的组件
import Home from './views/Home'
import About from './views/About'
const App = () => {
return (
<div>
{
/* 声明式导航 */}
<div>
{
/*
to 指定跳转到的路由地址
state 对象,隐式传递数据
replace boolean 是否可以回退
end它是5版本中的exact 严格匹配 ==> / 就是最后,后面没有匹配内容 boolean
激活样式默认的名称为active,如果你想修改它,则需要通过className={isActive=>isActive?'aa':''}
*/}
{
/* 对于首页导航自定义激活样式名称 */}
{
/* <NavLink end to="/" className={isActive => (isActive ? 'myactive' : '')}> */}
{
/* end={true}等价于end */}
<NavLink end to="/" state={
{
id: 1000 }}>首页</NavLink>
<span> --- </span>
<NavLink to="/about">关于</NavLink>
</div>
<hr />
<Routes>
<Route path='/' element={
<Home />} />
<Route path='/about' element={
<About />} />
</Routes>
</div>
)
}
export default App
重定向和404:
import React from 'react'
// 定义路由规则
import {
Routes, Route, Link, NavLink, Navigate } from 'react-router-dom'
// 路由匹配成功后要渲染的组件
import Home from './views/Home'
import About from './views/About'
const App = () => {
return (
<div>
{
/* 声明式导航 */}
<div>
<NavLink end to="/home" state={
{
id: 1000 }}>首页</NavLink>
<span> --- </span>
<NavLink to="/about">关于</NavLink>
</div>
<hr />
<Routes>
<Route path='/home' element={
<Home />} />
<Route path='/about' element={
<About />} />
{
/* 重定向 */}
<Route path="/" element={
<Navigate to="/home" replace={
false} />} />
{
/* 404页面处理 */}
<Route path="*" element={
<div>没有页面</div>} />
</Routes>
</div>
)
}
export default App
4. 编程式导航
关于组件:
import React from 'react'
import {
useNavigate } from 'react-router-dom'
const About = () => {
const navigate = useNavigate()
return (
<div>
<h3>关于我们</h3>
<hr />
<button
onClick={
() => {
// 回退
navigate(-1)
}}
>
回到首页
</button>
</div>
)
}
export default About
首页组件:
import React from 'react'
// 编程式导航,需要用到hook函数来得到导航对象,完成编程导航
import {
NavLink, useNavigate } from 'react-router-dom'
const Home = () => {
const navigate = useNavigate()
const jumpUrl = () => {
// 写法1
// 参数1:string/number string它就是一个url地址,number就是回退的步数 正向前 负向后
// 参数2:对象,可选,可以不写
// navigate('/about', {
// state: {}, // 隐式传递数据
// replace: true // 不可回退
// })
// 写法2
navigate('/about')
}
return (
<div>
<h3>首页页面</h3>
<hr />
<button onClick={
jumpUrl}>跳转到关于页面</button>
</div>
)
}
export default Home
5. 页面参数获取
import React from 'react'
import {
useLocation, useParams, useSearchParams } from 'react-router-dom'
// useParams 获取动态路由参数
// useSearchParams 获取search字符串
// useLocation location对象,可以得到state数据,得到pathname,得到search字符串
const Detail = () => {
const location = useLocation()
const params = useParams()
// search它是一个对象,URLSearchParams对象,可以用里面的get方法获取search中的字段数据
// setSearch 可以动态的修改当前search字符串中的字段数据,一般用不到
const [search, setSearch] = useSearchParams()
// 一般情况下是这种写法
// const [search] = useSearchParams()
return (
<div>
<h3>页面详情</h3>
<div>动态路由参数id:{
params.id}</div>
<div>state中的数据:{
location.state?.name}</div>
<div>search字符串中的age:{
search.get('age')}</div>
<button
onClick={
() => {
// 修改之后state中的数据会丢失
setSearch('?age=100')
}}
>
修改search字符串
</button>
</div>
)
}
export default Detail
6. 嵌套路由
父组件:
import React from 'react'
// 定义路由规则
import {
Routes, Route, Link, NavLink, Navigate } from 'react-router-dom'
// 路由匹配成功后要渲染的组件
import Home from './views/Home'
import About from './views/About'
import Detail from './views/Detail'
import Admin from './views/Admin'
import Welcome from './views/Welcome'
import User from './views/User'
const App = () => {
return (
<div>
{
/* 声明式导航 */}
<div>
<NavLink end to="/home" state={
{
id: 1000 }}>首页</NavLink>
<span> --- </span>
<NavLink to="/about">关于</NavLink>
<span> --- </span>
<NavLink to="/admin">后台</NavLink>
</div>
<hr />
<Routes>
{
/* 嵌套路由,就是把定义规则的Route由单标签更换成双标签就可以,里面还是要定义规则 */}
<Route path="/admin" element={
<Admin />}>
{
/* 嵌套路由 之 默认页 */}
<Route index element={
<Welcome />} />
{
/* path中开头不要写 / 就可以 ,它会自动把父组件中的path拼接过来 /admin/welcome */}
{
/* 非默认页,需要点击导航跳转 */}
{
/* <Route path="welcome" element={<Welcome />} /> */}
{
/* 重定向到欢迎页,重定向生效需要上一句代码 */}
{
/* <Route index element={<Navigate to="/admin/welcome" replace />} /> */}
<Route path="user" element={
<User />} />
</Route>
<Route path='/home' element={
<Home />} />
<Route path='/about' element={
<About />} />
{
/* 动态路由参数定义 */}
<Route path="/detail/:id" element={
<Detail />} />
{
/* 重定向 */}
{
/* Navigate重定向 to跳转到url地址 replace是否可以回退 */}
<Route path="/" element={
<Navigate to="/home" replace={
false} />} />
{
/* 404页面处理 */}
<Route path="*" element={
<div>没有页面</div>} />
</Routes>
</div>
)
}
export default App
后台首页组件:
import React from 'react'
import {
NavLink, Outlet } from 'react-router-dom'
const Admin = () => {
return (
<div>
<h3>后台管理</h3>
<div>
{
/* 没有默认页 */}
{
/* <NavLink to="/admin/welcome">首页</NavLink> */}
{
/* 显示默认页 */}
<NavLink to="/admin">首页</NavLink>
<span> -- </span>
<NavLink to="/admin/user">用户</NavLink>
</div>
<hr />
{
/* Admin组件它是一个父路由渲染的组件,它里面有嵌套路由,需要一个占位 */}
<Outlet />
</div>
)
}
export default Admin
7. useRoutes实现配置式路由
router/index.js:
import {
Navigate } from 'react-router-dom'
import Home from '../views/Home'
import About from '../views/About'
import Detail from '../views/Detail'
import Admin from '../views/Admin'
import Welcome from '../views/Welcome'
import User from '../views/User'
export default [
{
path: '/', element: <Navigate to="/home" replace /> },
{
path: '/home',
element: <Home />
},
{
path: '/about',
element: <About />
},
{
path: '/detail/:id',
element: <Detail />
},
{
path: '/admin',
element: <Admin />,
children: [
{
index: true, element: <Navigate to="/admin/welcome" replace /> },
{
path: 'welcome',
element: <Welcome />
},
{
path: 'user',
element: <User />
}
]
}
]
父组件:
import React from 'react'
import {
NavLink, useRoutes } from 'react-router-dom'
import routes from './router'
const App = () => {
const routeElement = useRoutes(routes)
return (
<div>
<div>
<NavLink to="/home">首页</NavLink>
<span> --- </span>
<NavLink to="/about">关于</NavLink>
<span> --- </span>
<NavLink to="/admin">后台</NavLink>
</div>
<hr />
{
routeElement}
</div>
)
}
export default App