React - Router 6.x 版本使用
React Router 6.0 :https://reactrouter.com/en/main/start/overview
一. 对比 ReactRouter 5.x 版本
- 包大小的不同 V5 大小在20.8k左右,压缩后在7.3k左右;V6 大小在10.8k左右,压缩后在3.8k左右
- 内置组件的变化:移除
<Switch/>
,新增<Routes/>
等。 - 语法的变化:
component={About}
变为element={<About/>}
等。 - 新增多个hook:
useParams
、useNavigate
、useMatch
等。 - 官方明确推荐使用函数式组件了。
二. Router 安装
yarn add react-router-dom@6.4.5
npm install react-router-dom@6.4.5
三. Component
1. 路由模式 BrowserRouter 和 HashRouter
6.x版本中
<HashRouter>
、<BrowserRouter>
的用法与 5.x 相同。
2. Routes 与 Route
- v6 版本中移除了先前的
<Switch>
,引入了新的替代者:<Routes>
。 <Routes>
和<Route>
要配合使用,且必须要用<Routes>
包裹<Route>
。<Route>
相当于一个 if 语句,如果其路径与当前 URL 匹配,则呈现其对应的组件。<Route caseSensitive>
属性用于指定:匹配时是否区分大小写(默认为 false)。- 当URL发生变化时,
<Routes>
都会查看其所有子<Route>
元素以找到最佳匹配并呈现组件 。 <Route>
也可以嵌套使用,且可配合useRoutes()
配置 “路由表” ,但需要通过<Outlet>
组件来渲染其子路由。
<Routes>
{/* path属性用于定义路径,element属性用于定义当前路径所对应的组件 */}
<Route path="/login" element={<Login />}></Route>
{/* 用于定义嵌套路由,home是一级路由,对应的路径/home */}
<Route path="home" element={<Home />}>
{/* page1 和 page2 是二级路由,对应的路径是/home/page1 或 /home/page2 */}
<Route path="page1" element={<Page1 />}></Route>
<Route path="page2" element={<Page2 />}></Route>
</Route>
{/*
Route也可以不写element属性, 表示用于展示嵌套的路由
./user 对应的路径是/users/user
/user 对应根路径/user
user 与./user意思相同,对应根路径/users/user
*/}
<Route path="users">
<Route path="user" element={<User />} />
</Route>
</Routes>
3. Link
- 用于修改URL,且不发送网络请求(路由链接)。
- 使用时,外侧需要用
<BrowserRouter>
或<HashRouter>
包裹。
import React from 'react'
export default function Demo() {
return (
<div>
<Link to="/路径">按钮</Link>
</div>
)
}
4. NavLink
- 与
<Link>
组件类似,且可实现导航的“高亮”效果 NavLink
默认类名是active
- 当
NavLink
上添加了end
属性后,若路由的子组件匹配成功,则路由的导航没有高亮效果。
{/* 自定义类名 */}
<NavLink
to="login"
className={({ isActive }) => {
console.log(isActive);
return isActive ? "class1" : "class2";
}}
>
login
</NavLink>
{/* 若Home的子组件匹配成功,则Home的导航没有高亮效果 */}
<NavLink to="home" end >home</NavLink>
5. Navigate
- 只要
<Navigate>
组件被渲染,就会修改路径,切换视图 replace
属性用于控制跳转模式(push 或 replace,默认是push)
import React, { useState } from "react";
import { Navigate } from "react-router-dom";
export default function Home() {
const [count, setCount] = useState(1);
return (
<div>
<h3>Home组件</h3>
{/* 根据count的值决定是否切换视图 */}
{count === 1 ? (
<h4>count的值为{count}</h4>
) : (
<Navigate to="/about" replace={true} />
)}
{/* 修改count值 */}
<button onClick={() => setCount(2)}>修改count值为2</button>
</div>
);
}
6. Outlet
当
<Route>
产生路由嵌套时,渲染其对应的后续子路由。
import React from "react";
import { NavLink, Outlet } from "react-router-dom";
export default function Home() {
return (
<div>
<h2>Home组件内容</h2>
<div>
{/* 子路由 */}
<ul>
<li>
<NavLink replace to="page1">page1</NavLink>
</li>
<li>
<NavLink to="page2">page2</NavLink>
</li>
</ul>
{/* 指定子路由组件呈现的位置 */}
<Outlet />
</div>
</div>
);
}
四. Hooks
1. useRoutes() —— 路由表
根据路由表,动态创建
<Routes>
和<Route>
。
- src 文件夹下创建 routes 文件夹,用于存放路由文件
- src/routes 文件夹下创建 index.js 文件,用于配置路由
//路由表配置: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" />, }, ];
- src/App.js 文件中引入使用
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 className="app"> <div className="menu"> {/* 路由链接 */} <NavLink to="/about">About</NavLink> <NavLink to="/home">Home</NavLink> </div> <div className="body"> {/* 路由组件 */} {element} </div> </div> ); }
- src/index.js 文件中使用
<BrowserRouter></BrowserRouter>
包裹<App />
import React from "react"; import ReactDOM from "react-dom/client"; import App from "./App"; import reportWebVitals from "./reportWebVitals"; import { BrowserRouter } from "react-router-dom/dist"; const root = ReactDOM.createRoot(document.getElementById("root")); root.render( <BrowserRouter> <App /> </BrowserRouter> ); reportWebVitals();
2. 路由传参
传递参数
id
,参数值为001
2.1 useParams() —— params传参
- 路由设置
// 路由表形式 { path: "detail/:id", element: <Detail />, },
// 标签形式 <Routes> <Route path="detail/:id" element={<Detail />} /> </Routes>
- 路由链接传参
<Link to={`detail/001`}>传参</Link>
- 接收参数
import React from "react"; import { useParams } from "react-router-dom"; export default function Detail() { // 接收参数 const { id, title, content } = useParams(); return <div>Detail</div>; }
2.2 useSearchParams() —— search传参(query传参)
- 路由设置
// 路由表形式 { path: "detail", element: <Detail />, },
// 标签形式 <Routes> <Route path="detail" element={<Detail />} /> </Routes>
- 路由链接传参
<Link to={`detail?id=001`}>传参</Link>
- 接收参数
import React from "react"; import { useSearchParams } from "react-router-dom"; export default function Detail() { // 返回一个包含两个值的数组,内容分别为:当前的seaech参数、更新search的函数 const [search, setSearch] = useSearchParams(); // 取出对应参数 const id = search.get("id"); return <div>Detail</div>; }
2.3 useLocation() —— state传参
- 路由设置
// 路由表形式 { path: "detail", element: <Detail />, },
// 标签形式 <Routes> <Route path="detail" element={<Detail />} /> </Routes>
- 路由链接传参
<Link to="detail" state={{ id: "001", }} > 传参 </Link>
- 接收参数
import React from "react"; import { useLocation } from "react-router-dom"; export default function Detail() { // 接收参数 const { state } = useLocation(); return <div>Detail</div>; }
3. useNavigate() —— 编程式路由导航
- 指定具体的路径
import React from "react"; import { useNavigate } from "react-router-dom"; export default function Demo() { const navigate = useNavigate(); const handle = () => { navigate( "detail", //指定路径 { replace: false, //是否为 replace 模式 state: { id: "001", //state 传参 }, } ); }; return ( <div> <button onClick={handle}>跳转</button> </div> ); }
- 传入数值,前进或后退
import React from "react"; import { useNavigate } from "react-router-dom"; export default function Demo() { const navigate = useNavigate(); const handle = () => { navigate(-1); // navigate(1); //前进 }; return ( <div> <button onClick={handle}>后退</button> </div> ); }
4. useInRouterContext() —— 判断组件是否在 Router的上下文中呈现
如果组件在
<Router>
的上下文中呈现,则useInRouterContext
钩子返回 true,否则返回 false。
import React from "react";
import { useInRouterContext } from "react-router-dom";
export default function Demo() {
// 打印判断
console.log(useInRouterContext());
return <div>Demo</div>;
}
5. useNavigationType() —— 返回当前的导航类型
- 返回当前的导航类型(用户是如何来到当前页面的)
- 返回值:
POP
、PUSH
、REPLACE
POP
是指在浏览器中直接打开了这个路由组件(刷新页面)
import React from "react";
import { useNavigationType } from "react-router-dom";
export default function Dome() {
// 打印查看
console.log(useNavigationType());
return <div>Dome</div>;
}
6. useOutlet() —— 呈现当前组件中渲染的嵌套路由
import React from "react";
import { NavLink, Outlet, useOutlet } from "react-router-dom";
export default function Home() {
/**
* useOutlet() 当前组件中渲染的嵌套路由
* 如果嵌套路由没有挂载,则result为null
* 如果嵌套路由已经挂载,则展示嵌套的路由对象
*/
console.log(useOutlet());
return (
<div>
<h2>Home组件内容</h2>
<div>
{/* 子路由 */}
<ul>
<li>
<NavLink replace to="page1">page1</NavLink>
</li>
<li>
<NavLink to="page2">page2</NavLink>
</li>
</ul>
{/* 指定子路由组件呈现的位置 */}
<Outlet />
</div>
</div>
);
}
7. useResolvedPath() —— 解析URL值
import React from "react";
import { useResolvedPath } from "react-router-dom";
export default function Demo() {
// 解析其中的:path、search、hash值
console.log(useResolvedPath("/user?id=001&name=tom#qwe"));
return <div>Demo</div>;
}