文章目录
- 1 一级路由
- 2 Navigate
- 3 NavLink 自定义高亮样式
- 4 useRoutes()
- 5 嵌套路由
- 6 路由传参
- 6.1 传递params参数
- 6.2 传递search参数
- 6.3 传递state参数
- 7 编程式导航
- 7.1 路由跳转
- 7.2 前进、后退
- 8 钩子函数
- 8.1 useInRouterContext()
- 8.2 useNavigationType()
- 8.3 useOutlet()
- 8.4 useResolvedPath()
- 9 小结
- 1. `<BrowserRouter>`
- 2. `<HashRouter>`
- 3. ` 与 `
- 4. `<Link>`
- 5. `<NavLink>`
- 6. `<Navigate>`
- 7. `<Outlet>`
- 3.Hooks
- 1. useRoutes()
- 2. useNavigate()
- 3. useParams()
- 4. useSearchParams()
- 5. useLocation()
- 6. useMatch()
- 7. useInRouterContext()
- 8. useNavigationType()
- 9. useOutlet()
- 10.useResolvedPath()
- 结语
1 一级路由
以之前讲解react-router-dom 5版本为例,做为基础使用:
第一步:安装react-router-dom@6.x版本
yarn add react-router-dom
第二步:<BrowserRouter></Browser>
包裹App
第三步:路由链接与注册路由,App.jsx源代码如下所示
import React, { Component } from 'react'
import { NavLink, Route, Routes } from "react-router-dom";
import About from './page/About';
import Home from './page/Home';
export default class App extends Component {
render() {
return (
<div>
<div className="row">
<div className="col-xs-offset-2 col-xs-8">
<div className="page-header"><h2>React Router Demo</h2></div>
</div>
</div>
<div className="row">
<div className="col-xs-2 col-xs-offset-2">
<div className="list-group">
<NavLink className='list-group-item' to="/about">About</NavLink>
<NavLink className='list-group-item' to="/home">Home</NavLink>
</div>
</div>
<div className="col-xs-6">
<div className="panel">
<div className="panel-body">
{/* 注册路由 */}
<Routes>
<Route path="/about" element={<About />} />
<Route path="/home" element={<Home />} />
</Routes>
</div>
</div>
</div>
</div>
</div>
)
}
}
- 注册路由组件必须
Routes包裹
,当匹配路径匹配某个路由的时候,不在继续向下匹配。
2 Navigate
router6 重定向使用Navigate,语法如下所示:
<Route path='/' element={<Navigate to="/about" replace={true}/>}></Route>
- 相当于兜底匹配,当不匹配上述所有的路由时,匹配该路由渲染to指向的路径对应的路由组件;
- to属性必须指定,表示要切换的路径;replace表示跳转模式,默认false即push模式;
- Navigate被渲染会引起视图切换。
3 NavLink 自定义高亮样式
router6中 className通过函数返回自定义样式
function computedClassName({isActive}) {
return isActive ? 'list-group-item g2zh' : 'list-group-item';
}
<NavLink className={computedClassName} to="/about">About</NavLink>
- 函数参数默认传递
{isActive: 布尔值}
,只有当前路由链接对应的值为true.
4 useRoutes()
router6我们通过配置路由表,根据路由表通过useRoutes生成路由规则。
第一步:配置路由表,routes/index.js源代码如下所示:
import { Navigate } from "react-router-dom";
import About from '../page/About';
import Home from '../page/Home';
const routes = [
{
path: '/about',
element: <About />
},
{
path: '/home',
element: <Home />
},
{
path: '/',
element: <Navigate to="/about" />
}
]
export default routes;
第二步:useRoutes()使用生成路由规则,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);
// ...省略
{/* 注册路由 */}
{ element }
// 省略
}
如下图所示:
5 嵌套路由
第一步:在路由配置表中通过children
,配置子路由
import { Navigate } from "react-router-dom";
import About from '../page/About';
import Home from '../page/Home';
import Message from '../page/Home/Message';
import News from '../page/Home/News';
const routes = [
{
path: '/about',
element: <About />
},
{
path: '/home',
element: <Home />,
children: [
{
path: 'message',
element: <Message />
},
{
path: 'news',
element: <News />
}
]
},
{
path: '/',
element: <Navigate to="/about" />
}
]
export default routes;
第二步:<Outlet/>
在需要展示子路由组件地方,Home/index.jsx代码如下
import React from 'react'
import { NavLink, Outlet } from 'react-router-dom';
export default function Home() {
return (
<div>
<h3>我是Home的内容</h3>
<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>
</div>
{/* 指定路由组件呈现的位置 */}
<Outlet />
</div>
)
}
- NavLink属性to可以只指定当前路径;
- 如果不需要父组件高亮,在父路由链接NavLink 中添加属性end。
效果如下图所示:
6 路由传参
6.1 传递params参数
第一步:Meseage/index.jsx路由嵌套,传递参数改写
import React, { useState } from 'react'
import { Link, Outlet } from 'react-router-dom'
export default function Message() {
const [messages, setMessages] = useState([
{ id: 1, title: '消息1', content: '锄禾日当午'},
{ id: 2, title: '消息2', content: '汗滴禾下土'},
{ id: 3, title: '消息3',content: '谁知盘中餐' },
{ id: 4, title: '消息4', content: '粒粒皆辛苦' }
])
return (
<div>
<ul>
{
messages.map((msg) => {
return (
<li key={msg.id}>
<Link to={`detail/${msg.id}/${msg.title}/${msg.content}`}>{msg.title}</Link>
</li>
)
})
}
</ul>
<hr />
<Outlet />
</div>
)
}
第二步:配置路由routes/index.js改写如下:
// 省略...
{
path: 'message',
element: <Message />,
children: [
{
path: 'detail/:id/:title/:content',
element: <Detail />
}]
},
// 省略...
第三部 Home/Message/Detail/index.jsx接受参数
import React from 'react'
import { useParams, useMatch } from "react-router-dom";
export default function Detail() {
const { id, title, content } = useParams();
// const { id, title, content } = useMatch('/home/message/detail/:id/:title/:content').params;
return (
<ul>
{/* <li>ID: xxx</li>
<li>TITLE: xxx</li>
<li>CONTENT: xxx</li> */}
<li>ID: {id}</li>
<li>TITLE: {title}</li>
<li>CONTENT: {content}</li>
</ul>
)
}
6.2 传递search参数
第一步:Meseage/index.jsx路由嵌套,传递参数改写
// 省略...
return (
<div>
<ul>
{
messages.map((msg) => {
return (
<li key={msg.id}>
<Link to={`detail/${msg.id}/${msg.title}/${msg.content}`}>{msg.title}</Link>
</li>
)
})
}
</ul>
<hr />
<Outlet />
</div>
)
}
第二步:配置路由routes/index.js改写如下:
// 省略...
{
path: 'message',
element: <Message />,
children: [
{
path: 'detail',
element: <Detail />
}]
},
// 省略...
第三部 Home/Message/Detail/index.jsx接受参数
import React from 'react'
import { useSearchParams } from "react-router-dom";
export default function Detail() {
const [searchParams, setSearchParams] = useSearchParams();
const id = searchParams.get('id');
const title = searchParams.get('title');
const content = searchParams.get('content');
return (
<ul>
{/* <li>ID: xxx</li>
<li>TITLE: xxx</li>
<li>CONTENT: xxx</li> */}
<li>ID: {id}</li>
<li>TITLE: {title}</li>
<li>CONTENT: {content}</li>
</ul>
)
}
- useSearchParams()用法类似useState()
6.3 传递state参数
第一步:Meseage/index.jsx路由嵌套,传递参数改写
// 省略...
return (
<div>
<ul>
{
messages.map((msg) => {
return (
<li key={msg.id}>
<Link to="detail" state={{id: msg.id, title: msg.title, content: msg.content}}>{msg.title}</Link>
</li>
)
})
}
</ul>
<hr />
<Outlet />
</div>
)
}
第二步:配置路由routes/index.js改写如下:
// 省略...
{
path: 'message',
element: <Message />,
children: [
{
path: 'detail',
element: <Detail />
}]
},
// 省略...
第三部 Home/Message/Detail/index.jsx接受参数
import React from 'react'
import { useLocation } from "react-router-dom";
export default function Detail() {
const {state: {id, title, content}} = useLocation()
// ...省略
7 编程式导航
7.1 路由跳转
第一步:添加按钮事件
<button onClick={() => showDetail(msg)}>查看详情</button>
第二步:引入useNavigate钩子函数,实现带参跳转
import { Link, Outlet, useNavigate } from 'react-router-dom'
const navigate = useNavigate()
// 查看详情
function showDetail(msg) {
// console.log('查看这消息的跟路吧');
navigate('detail', {
state: {
id: msg.id,
title: msg.title,
content: msg.content
}
})
}
7.2 前进、后退
在普通组件components/Header/index.jsx代码如下
import React from 'react'
import { useNavigate } from "react-router-dom";
export default function Header() {
const navigate = useNavigate();
/**
* 前进
*/
function forward (){
navigate(1)
}
/**
* 后退
*/
function back () {
navigate(-1)
}
return (
<div className="col-xs-offset-2 col-xs-8">
<div className="page-header"><h2>React Router Demo</h2></div>
<button onClick={forward}>前进</button>
<button onClick={back}>后退</button>
</div>
)
}
8 钩子函数
8.1 useInRouterContext()
如果组件被选择在路由上下文中,直观理解就是被包裹在<Router>
中,返回true
;否则返回false
。
示例在App.jsx中:
import { useInRouterContext } from "react-router-dom";
console.log('---', useInRouterContext());
// 输出
--- true
8.2 useNavigationType()
- 左右返回当前路由导航的类型(用户如何来到当前页面的)。
- 返回值:POP、PUSH、REPLACE。
- 备注:POP指在浏览器中直接打开这个路由组件(刷新页面)。
示例News/index.jsx
import { useNavigationType } from "react-router-dom";
console.log('===', useNavigationType());
// 输出默认PUSH
=== PUSH
// 路由链接加上 replace
=== REPLACE
// 直接刷新页面
=== POP
8.3 useOutlet()
-
作用:用来呈现当前组件中渲染的嵌套路由
-
示例Home/index.jsx:
// 从根路径开始,点击Home导航 @@ null // 点击子路由 @@ {$$typeof: Symbol(react.element), type: {…}, key: null, ref: null, props: {…}, …}
- 如果嵌套路由没有挂载,则为null;如果嵌套路由已挂载,则展示嵌套的路由对象。
8.4 useResolvedPath()
-
作用:给定一个URL值,解析其中的:path、search、hash值。
-
示例:
import { useResolvedPath } from "react-router-dom"; console.log('@@@', useResolvedPath('/news?id=1&title=abc#xxx')); // 输出 {pathname: '/news', search: '?id=1&title=abc', hash: '#xxx'}
9 小结
1. <BrowserRouter>
- 说明:
<BrowserRouter>
用于包裹整个应用。
2. <HashRouter>
- 说明:作用与
<BrowserRouter>
一样,但<HashRouter>
修改的是地址栏的hash值。 - 备注:6.x版本中
<HashRouter>
、<BrowserRouter>
的用法与 5.x 相同。
3. <Routes/> 与 <Route/>
- v6版本中移出了先前的
<Switch>
,引入了新的替代者:<Routes>
。 <Routes>
和<Route>
要配合使用,且必须要用<Routes>
包裹<Route>
。<Route>
相当于一个 if 语句,如果其路径与当前 URL 匹配,则呈现其对应的组件。<Route caseSensitive>
属性用于指定:匹配时是否区分大小写(默认为 false)。- 当URL发生变化时,
<Routes>
都会查看其所有子<Route>
元素以找到最佳匹配并呈现组件 。 <Route>
也可以嵌套使用,且可配合useRoutes()
配置 “路由表” ,但需要通过<Outlet>
组件来渲染其子路由。
4. <Link>
-
作用: 修改URL,且不发送网络请求(路由链接)。
-
注意: 外侧需要用
<BrowserRouter>
或<HashRouter>
包裹。
5. <NavLink>
- 作用: 与
<Link>
组件类似,且可实现导航的“高亮”效果。
6. <Navigate>
-
作用:只要
<Navigate>
组件被渲染,就会修改路径,切换视图。 -
replace
属性用于控制跳转模式(push 或 replace,默认是push)。
7. <Outlet>
- 当
<Route>
产生嵌套时,渲染其对应的后续子路由。
3.Hooks
1. useRoutes()
- 作用:根据路由表,动态创建
<Routes>
和<Route>
。
2. useNavigate()
- 作用:返回一个函数用来实现编程式导航。
3. useParams()
- 作用:回当前匹配路由的
params
参数,类似于5.x中的match.params
。
4. useSearchParams()
- 作用:用于读取和修改当前位置的 URL 中的查询字符串。
- 返回一个包含两个值的数组,内容分别为:当前的seaech参数、更新search的函数。
5. useLocation()
- 作用:获取当前 location 信息,对标5.x中的路由组件的
location
属性。
6. useMatch()
- 作用:返回当前匹配信息,对标5.x中的路由组件的
match
属性。
7. useInRouterContext()
作用:如果组件在 `<Router>` 的上下文中呈现,则 `useInRouterContext` 钩子返回 true,否则返回 false。
8. useNavigationType()
- 作用:返回当前的导航类型(用户是如何来到当前页面的)。
- 返回值:
POP
、PUSH
、REPLACE
。 - 备注:
POP
是指在浏览器中直接打开了这个路由组件(刷新页面)。
9. useOutlet()
- 作用:用来呈现当前组件中渲染的嵌套路由。
10.useResolvedPath()
- 作用:给定一个 URL值,解析其中的:path、search、hash值。
结语
❓QQ:806797785
⭐️源代码仓库地址:https://github.com/gaogzhen/react-staging.git
参考:
[1]React视频教程[CP/OL].2020-12-15.p127-141.
[2]React官网[CP/OL].