嵌套路由及传参

Tutorial: React基础 Category: React Published: 2026-04-07 13:58:26 Views: 20 Likes: 0 Comments: 0

嵌套路由及传参方式和常用 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 路由组件
  1. 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>&nbsp;
            <NavLink to="message">Message</NavLink>
            {/* 指定路由组件展示位置 */}
            <Outlet />
          </div>
        </div>
      );
    }
    
  2. 二级路由 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>
      );
    }
    
  3. 三级路由 Detail

    import React from "react";
    
    export default function Detail() {
      return (
        <div>
          <ul>
            <li>111</li>
            <li>222</li>
            <li>333</li>
          </ul>
        </div>
      );
    }
    
三、路由传参 params 形式
  1. 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>
      );
    }
    
  2. 调整路由表

    const routes = [
     ...
      {
        path: "/home",
        element: <Home />,
        children: [
          {
            path: "news",
            element: <News />,
          },
          {
            path: "message",
            element: <Message />,
            children: [
              {
                path: "detail/:id/:title/:content",
                element: <MsgDetail />,
              },
            ],
          },
        ],
      },
      ...
    ];
    
  3. 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 形式
  1. 路由表还原

    const routes = [
     ...
      {
        path: "/home",
        element: <Home />,
        children: [
          {
            path: "news",
            element: <News />,
          },
          {
            path: "message",
            element: <Message />,
            children: [
              {
                path: "detail",
                element: <MsgDetail />,
              },
            ],
          },
        ],
      },
      ...
    ];
    
  2. 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>
      );
    }
    
  3. 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 形式
  1. Message 修改传参方式

    export default function Message() {
      return (
        ...
        <Link
          to="detail"
          state={{
            id: item.id,
            title: item.title,
            content: item.content,
          }}
        >
          {item.title}
        </Link>
        ...
      );
    }
    
  2. 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>
      );
    }
    
六、编程式路由导航
  1. 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
  1. 任何组件或者元素是否被 BrowserRouter、HashRouter 包裹
    console.log(useInRouterContext()); // true
    
  2. 返回当前的导航类型 POP(刷新页面)/PUSH/REPLACE
    console.log(useNavigationType()); // POP
    
  3. 呈现当前组建中渲染的嵌套路由, null 为当前页面组件还未挂载
    console.log(useOutlet());
    
  4. 解析 URL
    console.log(useResolvedPath("/d1/d2?id=123&title=hello#qwe"));
    // {pathname: '/d1/d2', search: '?id=123&title=hello', hash: '#qwe'}