ThatManK Mobile Article
嵌套路由及传参
嵌套路由及传参方式和常用 Hook
一、路由表
import { Navigate } from "react-router-dom";
// 一级路由
import Home from "../pages/Home";
import About from "../pages/About";
// Home 下的二级路由
import News from "../pages/News";
import Message from "../pages/Message";
// Message 下的三级路由
import MsgDetail from "../pages/Detail";
const routes = [
{
path: "/about",
element: <About />,
},
{
path: "/home",
element: <Home />,
children: [
{
path: "news",
element: <News />,
},
{
path: "message",
element: <Message />,
children: [
{
path: "detail",
element: <MsgDetail />,
},
],
},
],
},
{
path: "/",
element: <Navigate to="/home" />,
},
];
export default routes;
二、Home 路由组件
- Home 组件内容
import React, { useState } from "react";
import { Navigate, NavLink, Outlet } from "react-router-dom";
export default function Home() {
const [sum, setSum] = useState(0);
const addSum = () => {
setSum(sum + 1);
};
return (
<div>
<h3>我是home的内容</h3>
{sum === 3 ? <Navigate to="/about" /> : <p>{sum}</p>}
<button onClick={addSum}>点击变成2</button>
<div>
<NavLink to="news">News</NavLink>
<NavLink to="message">Message</NavLink>
{/* 指定路由组件展示位置 */}
<Outlet />
</div>
</div>
);
}
- 二级路由 Message
import React, { useState } from "react";
import { Link, Outlet } from "react-router-dom";
export default function Message() {
const [msgs, setMsgs] = useState([
{ id: "001", title: "消息1", content: "锄禾日当午," },
{ id: "002", title: "消息2", content: "汗滴禾下土." },
{ id: "003", title: "消息3", content: "谁知盘中餐," },
{ id: "004", title: "消息4", content: "粒粒皆辛苦." },
]);
return (
<div>
<ul>
{msgs.map((item) => {
return (
<li key={item.id}>
<Link to="detail">{item.title}</Link>
</li>
);
})}
</ul>
{/* 指定路由组件展示位置 */}
<Outlet />
</div>
);
}
- 三级路由 Detail
import React from "react";
export default function Detail() {
return (
<div>
<ul>
<li>111</li>
<li>222</li>
<li>333</li>
</ul>
</div>
);
}
三、路由传参 params 形式
- Message
import React, { useState } from "react";
import { Link, Outlet } from "react-router-dom";
export default function Message() {
const [msgs, setMsgs] = useState([
{ id: "001", title: "消息1", content: "锄禾日当午," },
{ id: "002", title: "消息2", content: "汗滴禾下土." },
{ id: "003", title: "消息3", content: "谁知盘中餐," },
{ id: "004", title: "消息4", content: "粒粒皆辛苦." },
]);
return (
<div>
<ul>
{msgs.map((item) => {
return (
<li key={item.id}>
<Link to={`detail/${item.id}/${item.title}/${item.content}`}>
{item.title}
</Link>
</li>
);
})}
</ul>
{/* 指定路由组件展示位置 */}
<Outlet />
</div>
);
}
- 调整路由表
const routes = [
...
{
path: "/home",
element: <Home />,
children: [
{
path: "news",
element: <News />,
},
{
path: "message",
element: <Message />,
children: [
{
path: "detail/:id/:title/:content",
element: <MsgDetail />,
},
],
},
],
},
...
];
- Detail 接受参数并渲染
import React from "react";
import { useMatch, useParams } from "react-router-dom";
export default function Detail() {
const { id, title, content } = useParams();
const x = useMatch("/home/message/detail/:id/:title/:content");
console.log(x);
return (
<div>
<ul>
<li>{id}</li>
<li>{title}</li>
<li>{content}</li>
</ul>
</div>
);
}
四、路由传参 search 形式
- 路由表还原
const routes = [
...
{
path: "/home",
element: <Home />,
children: [
{
path: "news",
element: <News />,
},
{
path: "message",
element: <Message />,
children: [
{
path: "detail",
element: <MsgDetail />,
},
],
},
],
},
...
];
- Message 调整传参方式
export default function Message() {
const [msgs, setMsgs] = useState([
{ id: "001", title: "消息1", content: "锄禾日当午," },
{ id: "002", title: "消息2", content: "汗滴禾下土." },
{ id: "003", title: "消息3", content: "谁知盘中餐," },
{ id: "004", title: "消息4", content: "粒粒皆辛苦." },
]);
return (
<div>
<ul>
{msgs.map((item) => {
return (
<li key={item.id}>
<Link
to={`detail?id=${item.id}&title=${item.title}&content=${item.content}`}
>
{item.title}
</Link>
</li>
);
})}
</ul>
{/* 指定路由组件展示位置 */}
<Outlet />
</div>
);
}
- Detail 接收参数
import React from "react";
import { useLocation, useSearchParams } from "react-router-dom";
export default function Detail() {
// 方法1
const [search, setSearch] = useSearchParams();
const obj = {
id: search.get("id"),
title: search.get("title"),
content: search.get("content"),
};
// 方法2
const x = useLocation();
console.log(x);
console.log(x.search);
// ?id=123&title=234&content=345
return (
<div>
<ul>
<li>{obj.id}</li>
<li>{obj.title}</li>
<li>{obj.title}</li>
</ul>
{/* 不能更新单个,只更新一个的话, 会认为其他参数没传 */}
<button onClick={() => setSearch("id=123&title=234&content=345")}>
点我更新参数
</button>
</div>
);
}
五、路由传参 state 形式
- Message 修改传参方式
export default function Message() {
return (
...
<Link
to="detail"
state={{
id: item.id,
title: item.title,
content: item.content,
}}
>
{item.title}
</Link>
...
);
}
- Detail 接收
import { useLocation } from "react-router-dom";
export default function Detail() {
const { state } = useLocation();
return (
<div>
<ul>
<li>{state.id}</li>
<li>{state.title}</li>
<li>{state.content}</li>
</ul>
</div>
);
}
六、编程式路由导航
- useNavigate 的使用, Message 修改传参方式即可, Detail 不用改
import { Link, Outlet, useNavigate } from "react-router-dom";
export default function Message() {
const navigate = useNavigate();
const showDetail = (item) => {
navigate("detail", {
// replace: false,
state: {
id: item.id,
title: item.title,
content: item.content,
},
});
};
return (
...
<li key={item.id}>
<Link
to="detail"
state={{
id: item.id,
title: item.title,
content: item.content,
}}
>
{item.title}
</Link>
<button onClick={() => showDetail(item)}>点我查看详情</button>
</li>
...
);
}
七、其他几个 hook
- 任何组件或者元素是否被 BrowserRouter、HashRouter 包裹
console.log(useInRouterContext()); // true
- 返回当前的导航类型 POP(刷新页面)/PUSH/REPLACE
console.log(useNavigationType()); // POP
- 呈现当前组建中渲染的嵌套路由, null 为当前页面组件还未挂载
console.log(useOutlet());
- 解析 URL
console.log(useResolvedPath("/d1/d2?id=123&title=hello#qwe"));
// {pathname: '/d1/d2', search: '?id=123&title=hello', hash: '#qwe'}