react路由-v6
React Router 6 快速上手
1. 准备
1.1. 单页应用
- SPA (single page application): 单页应用
- 也就是整个应用只有一个页面, 页面切换时, 做局部页面更新 (可能要获取新的数据 )
- 好处: 加载数据少, 基本不会出现切换页面时空白的情况
- 现代的前端应用很多都是SPA
1.2. 路由
路由: 一个 key: value 的映射组合
后端路由: path 与处理请求的回调及请求方式的映射组合
1
app.get('/getUser', (req, res) => {})
前台路由: path 与 路由组件的映射组合
1
2<Route path='/about' element={<About/>}></Route>
<Route path='/home' element={<Home/>}></Route>当请求某个路由路径时, 浏览器不会发请求, 而是在局部显示对应的路由组件
==路由组件放在pages文件夹里==
2. 概述
React Router 以三个不同的包发布到 npm 上,它们分别为:
- react-router: 路由的核心库,提供了很多的:组件、钩子。
- react-router-dom: 包含react-router所有内容,并添加一些专门用于 DOM 的组件,例如
等 。 - 网页端使用的库
- react-router-native: 包括react-router所有内容,并添加一些专门用于ReactNative的API,例如:
等。 - 移动端使用的库
与React Router 5.x 版本相比,改变了什么?
内置组件的变化:移除
<Switch/>,新增<Routes/>等。语法的变化:
component={About}变为element={<About/>}等。新增多个hook:
useParams、useNavigate、useRoutes等。官方明确推荐函数式组件了!!!
……
3. 内置组件
3.1. <BrowserRouter>
说明:
<BrowserRouter>用于包裹整个应用App。示例代码:
1
2
3
4
5
6
7
8
9import React from "react";
import ReactDOM from "react-dom";
import { BrowserRouter } from "react-router-dom";
ReactDOM.render(
<BrowserRouter>
{/* 整体结构(通常为App组件) */}
</BrowserRouter>,root
);
3.2. <HashRouter>
- 说明:作用与
<BrowserRouter>一样,但<HashRouter>的路由路径在地址中带#。 - 备注:6.x版本中
<HashRouter>、<BrowserRouter>的用法与 5.x 相同。
3.3. <Routes/>与<Route/>
v6版本中移出了先前的
<Switch>,引入了新的替代者:<Routes>。<Routes>和<Route>要配合使用,且必须要用<Routes>包裹<Route>。<Route>相当于一个 if 语句,如果其路径与当前 URL 匹配,则呈现其对应的组件。<Route caseSensitive>属性用于指定:匹配时是否区分大小写(默认为 false)。当URL发生变化时,
<Routes>都会查看其所有子<Route>元素以找到最佳匹配并呈现组件 。<Route>也可以嵌套使用,且可配合useRoutes()配置 “路由表” ,但需要通过<Outlet>组件来渲染其子路由。示例代码:
1
2
3
4
5
6
7
8
9
10
11<Routes>
{/* path属性用于定义路径,element属性用于定义当前路径所对应的组件 */}
<Route path="/login" element={<Login />}></Route>
{/* 用于定义嵌套路由,home是一级路由,对应的路径/home */}
<Route path="home" element={<Home />}>
{/* test1 和 test2 是二级路由,对应的路径是/home/test1 或 /home/test2 */}
<Route path="test1" element={<Test/>}></Route>
<Route path="test2" element={<Test2/>}></Route>
</Route>
</Routes>
3.4. <Link>
作用: 修改URL,且不发送网络请求(路由链接)。
注意: 外侧需要用
<BrowserRouter>或<HashRouter>包裹。示例代码:
1
2
3
4
5
6
7
8
9import { Link } from "react-router-dom";
function Test() {
return (
<div>
<Link to="/路径">按钮</Link>
</div>
);
}
3.5. <NavLink>
作用: 与
<Link>组件类似,且可实现导航的“高亮”效果。示例代码:
1
2
3
4
5
6
7
8
9
10// 注意: NavLink默认类名是active,下面是指定自定义的class
//自定义样式
<NavLink
to="login"
className={({ isActive }) => {
console.log('home', isActive)
return isActive ? 'base atguigu' : 'base'
}}
>login</NavLink>
3.6. <Navigate>
作用:只要
<Navigate>组件被渲染,就会修改路径,切换视图。相当于重定向replace属性用于控制跳转模式(push 或 replace,默认是push)。示例代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14import React,{useState} from 'react'
import {Navigate} from 'react-router-dom'
export default function Home() {
const [sum,setSum] = useState(1)
return (
<div>
<h3>我是Home的内容</h3>
{/* 根据sum的值决定是否切换视图 */}
{sum === 1 ? <h4>sum的值为{sum}</h4> : <Navigate to="/about" replace={true}/>}
<button onClick={()=>setSum(2)}>点我将sum变为2</button>
</div>
)
}
3.7. <Outlet>
当
<Route>产生嵌套时,渲染匹配的子路由。示例代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45//根据路由表生成对应的路由规则
const element = useRoutes([
{
path:'/about',
element:<About/>
},
{
path:'/home',
element:<Home/>,
children:[
{
path:'news',
element:<News/>
},
{
path:'message',
element:<Message/>,
}
]
}
])
//Home.js
import React from 'react'
import {NavLink,Outlet} from 'react-router-dom'
export default function Home() {
return (
<div>
<h2>Home组件内容</h2>
<div>
<ul className="nav nav-tabs">
<li>
<NavLink className="list-group-item" to="news">News</NavLink>
</li>
<li>
<NavLink className="list-group-item" to="message">Message</NavLink>
</li>
</ul>
{/* 指定路由组件呈现的位置 */}
<Outlet />
</div>
</div>
)
}
4. 内置 Hooks
4.1. useRoutes()
作用:根据路由表,动态创建
<Routes>和<Route>。示例代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38//路由表配置:src/routes/index.js
import About from '../pages/About'
import Home from '../pages/Home'
import {Navigate} from 'react-router-dom'
export default [
{
path:'/about',
element:<About/>
},
{
path:'/home',
element:<Home/>
},
{
path:'/',
element:<Navigate to="/about"/>
}
]
//App.jsx
import React from 'react'
import {NavLink,useRoutes} from 'react-router-dom'
import routes from './routes'
export default function App() {
//根据路由表生成对应的路由规则
const element = useRoutes(routes)
return (
<div>
......
{/* 注册路由 */}
{element}
......
</div>
)
}
4.2. useNavigate()
作用:返回一个函数用来==实现编程式导航==。即点击,实现路由切换
示例代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24import React from 'react'
import {useNavigate} from 'react-router-dom'
export default function Demo() {
const navigate = useNavigate()
const handle = () => {
//第一种使用方式:指定具体的路径
navigate('/login', {
replace: false,
state: {a:1, b:2}
})
// 前进
// navigate(1)
// 后退
// navigate(-1)
}
return (
<div>
<button onClick={handle}>按钮</button>
</div>
)
}
4.3. useParams()
作用:返回当前匹配路由的
params参数的对象,类似于5.x中的match.params。示例代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23import { useParams } from "react-router-dom"
export default function MessageDetail() {
// 读取传递过来的params参数
const {id, title, content} = useParams()
return (
<ul>
<li>id: {id}</li>
<li>title: {title}</li>
<li>content: {content}</li>
</ul>
)
}
// 注册路由
{
path: 'detail/:id/:title/:content',
element: <MessageDetail/>
}
// 路由链接
<Link to={`detail/${m.id}/${m.title}/${m.content}`}>{m.title}</Link>
4.4. useSearchParams()
作用:用于读取和修改当前位置的 URL 中的查询字符串。
返回一个包含两个值的数组,内容分别为:当前的seaech参数、更新search的函数。
示例代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29import {useSearchParams} from 'react-router-dom'
export default function Detail() {
const [search,setSearch] = useSearchParams()
const id = search.get('id')
const title = search.get('title')
const content = search.get('content')
return (
<ul>
<li>
<button onClick={()=>setSearch('id=008&title=哈哈&content=嘻嘻')}>
点我更新一下收到的search参数</button>
</li>
<li>消息编号:{id}</li>
<li>消息标题:{title}</li>
<li>消息内容:{content}</li>
</ul>
)
}
// 注册路由
{
path: 'detail',
element: <MessageDetail/>
}
// 路由链接
<Link to={`detail?id=${m.id}&title=${m.title}&content=${m.content}`}>{m.title}</Link>
4.5. useLocation()
作用:获取当前 location 信息,对标5.x中的路由组件的
location属性。示例代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35import React from 'react'
import {useLocation} from 'react-router-dom'
export default function Detail() {
const x = useLocation()
console.log(x)
// x就是location对象:
/*
{
hash: "",
key: "ah9nv6sz",
pathname: "/login",
search: "?name=zs&age=18",
state: {id: '001', title: 'm1', content: 'abcd'}
}
*/
const {state: {id, title, content}} = x
return (
<ul>
<li>消息编号:{id}</li>
<li>消息标题:{title}</li>
<li>消息内容:{content}</li>
</ul>
)
}
// 注册路由
{
path: 'detail',
element: <MessageDetail/>
}
// 路由链接
<Link to={`detail`} state={m}>{m.title}</Link>
5. 路由懒加载
问题:
所有路由组件代码是打包在一些的, 打开首页就会加载, 但我们开始只需要看到首页路由的效果,
也就是只需要执行首页路由组件代码解决:
对路由组件进行懒加载处理深入理解
对路由组件进行拆分/单独打包 => import函数动态引入
访问路由时才去后台加载对应的打包文件 => lazy函数
指定loading界面 =><Suspense fallback={loading界面}>
文档: https://react.docschina.org/docs/react-api.html#reactlazy
1 | import {lazy, Suspense} from 'react' |
路由传参总结
params
路径需要有占位符: /detail/:id/:title/:content
- /src/routes/index.js
- 占位符中指定的占位变量,会在接收数据的时候,对应同样的变量名
跳转链接
- pages/Message.jsx
1
<Link to={`detail/${m.id}/${m.title}/${m.content}`}>{m.title}</Link>
获取数据:
- 使用useParams Hook
1
2import {useParams} from 'react-router-dom'
let params = useParams();
searchParams
- (路由表中的)路径不需要占位: /路径?key=value&key2=value2
1 | /src/routes/index.js |
- 跳转链接 ?key=value&key2=value
1 | <Link to={`detail?id3=${m.id}&title3=${m.title}&content3=${m.content}`}>{m.title}</Link> |
获取数据【/pages/Detail.jsx】
- useSearchParams Hook 获取
- 语法
1
2
3
4let [searchParams,setSearchParams] = useSearchParams();
let id = searchParams.get('id3');
let title = searchParams.get('title3');
let content = searchParams.get('content3');
state
- 配置路由表【跟普通路由链接一样】
1 | { |
- 配置链接
1 | // 路由链接 |
- 接收 useLocation
1 | let {state:{id,title,content}} = useLocation(); |
三种参数传递的选择
- 如果数据量比较多,比较大,优先选择使用state
- 数据不会出现在地址栏。
- 可以直接传对象数据类型
- 如果数据量不大,可以考虑使用params传递
