ThatManK Mobile Article

嵌套路由及传参

Category: React Tutorial: React基础 Published: 2026-04-07 13:58 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>
     );
   }
  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.title}</Link>
               </li>
             );
           })}
         </ul>
         {/* 指定路由组件展示位置 */}
         <Outlet />
       </div>
     );
   }
  1. 三级路由 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>
     );
   }
  1. 调整路由表
   const routes = [
    ...
     {
       path: "/home",
       element: <Home />,
       children: [
         {
           path: "news",
           element: <News />,
         },
         {
           path: "message",
           element: <Message />,
           children: [
             {
               path: "detail/:id/:title/:content",
               element: <MsgDetail />,
             },
           ],
         },
       ],
     },
     ...
   ];
  1. 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 />,
             },
           ],
         },
       ],
     },
     ...
   ];
  1. 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>
     );
   }
  1. 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>
        ...
      );
    }
  1. 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
  1. 返回当前的导航类型 POP(刷新页面)/PUSH/REPLACE
    console.log(useNavigationType()); // POP
  1. 呈现当前组建中渲染的嵌套路由, null 为当前页面组件还未挂载
    console.log(useOutlet());
  1. 解析 URL
    console.log(useResolvedPath("/d1/d2?id=123&title=hello#qwe"));
    // {pathname: '/d1/d2', search: '?id=123&title=hello', hash: '#qwe'}