react学习-路由的使用

01 一级路由

安装包

在使用路由时,要下载react-router-dom

npm i -D react-router-dom

引入路由

使用路由时需要将路由包裹代码效果如下

其中,BrowserRouter 更好,HashRouter 有兼容性问题

// `BrowserRouter` 更好,`HashRouter` 有兼容性问题
import { BrowserRouter, HashRouter } from "react-router-dom";

const root = ReactDOM.createRoot(
  document.getElementById("root") as HTMLElement
);
root.render(
  <React.StrictMode>
    <BrowserRouter>
      <App />
    </BrowserRouter>
  </React.StrictMode>
);

路由的使用

在点击路由链接时需要跳转到相应页面,在这使用的是route6版本

react-router-dom中分别引入如下所示

import { NavLink, Routes, Route } from "react-router-dom";
  • NavLink如果需要高亮,Link不需要高亮

  • Routes相当于之前的switch

NavLink使用

使用方式如下所示,在后面章节中会详细提出更多使用方式

<NavLink className="list-group-item" to="/about">
  About
</NavLink>
<NavLink className="list-group-item" to="/home">
  Home
</NavLink>

注册路由

  • 注册路由:

  • 如果想写标签就用element 不想用标签就用 Component

  • 和之前一样,如果有相同标签则会匹配第一次也就是第一个匹配到的组件

代码效果如下所示:

  <Routes>
    <Route path="/about" element={<About />} />
    <Route path="/home" element={<Home />} />
    <Route path="/about" Component={About} />
    <Route path="/home" Component={Home} />
  </Routes>

展现标签在element后面写入,或者在Component写入

02 路由重定向

如果是在访问根路由的情况下,这时需要路由的重定向操作

在route6版本中引入了新的组件标签Navigate,可以组件中使用重定向

在实际的开发中当路由较多时会使用路由表统一管理

点击路由链接

点击路由链接写法和在01中方式一样没有改变

<NavLink className="list-group-item" to="/about">
  About
</NavLink>
<NavLink className="list-group-item" to="/home">
  Home
</NavLink>

路由重定向

如要引入的包

  • NavLink如果需要高亮,Link不需要高亮
  • Routes相当于之前的switch
import { NavLink, Routes, Route, Navigate } from "react-router-dom";

代码展示

  • 当访问根路径时候,会重定向到当前设置的路由中
  • 如果在标签中引入了Navigate当路由变化时必然会引起视图的切换
  • 在页面中会自动跳转到 about 页面
  • caseSensitive会区分大小写
<Routes>
    <Route path="/about" caseSensitive element={<About />} />
    <Route path="/home" element={<Home />} />
    <Route path="/" element={<Navigate to="/about" />} />
</Routes>

符合条件跳转

  • 如果 to 不写会报错,没有pathname
  • replace={true} 会替换当前页面,效果就是不会后退页面了;默认是push
<>
  <h3>我是Home的内容</h3>
  {sum === 2 ? (
    <Navigate to="/about" replace={true} />
  ) : (
    <h4>当前的sum值为:{sum} </h4>
  )}
  <button className="btn btn-primary" onClick={() => setSum(sum + 1)}>
    改变sum值
  </button>
</>

03 带高亮效果

在使用bootstrap框架时帮我们定义了好了,如果点击就会自动加上active

如何加上自己想要的样式

const computedClassName = ({ isActive }: any) => {
return isActive ? "list-group-item bunny" : "list-group-item";
};
return(
<NavLink className={computedClassName} to="/about">
  About
</NavLink>
<NavLink className={computedClassName} to="/home">
  Home
</NavLink>
)

不让父级高亮

  • 点击链接进行跳转------开始
  • 如果不想让父级路由高亮 在标签中写上end
  • 实例 <NavLink className="list-group-item" end to="/about">
<NavLink className="list-group-item" end to="/about">
  About
</NavLink>
<NavLink className="list-group-item" to="/home">
  Home
</NavLink>

04 路由表的使用

创建路由表

src目录下新建routes/index.tsx

内容如下展示

import { Navigate } from "react-router-dom";
import About from "../page/About";
import Home from "../page/Home";

export default [
  { path: "/about", element: <About /> },
  { path: "/home", element: <Home /> },
  { path: "/", element: <Navigate to="about" /> },
];

需要将木块暴露出去

引入路由表

之后在组件中接受

需要引入包

import { NavLink, useRoutes } from "react-router-dom";
import element from "./routes";
// 定义路由表
const elementList = useRoutes(element);

组件中使用

export default function App() {
  const elementList = useRoutes(element);
  return (
    <>
      <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">
              {/* 路由表的使用 */}
              {elementList}
            </div>
          </div>
        </div>
      </div>
    </>
  );
}

05 嵌套路由

路由表中

routes/index.tsx

嵌套路由和vue比较像,在父级路由中需要写上children;以数组的形式

import { Navigate } from "react-router-dom";
import About from "../page/About";
import Home from "../page/Home";
import Message from "./../page/Message";
import News from "./../page/News";

export default [
  { path: "/about", element: <About /> },
  {
    path: "/home",
    element: <Home />,
    children: [
      { path: "message", element: <Message /> },
      { path: "news", element: <News /> },
    ],
  },
  { path: "/", element: <Navigate to="about" /> },
];

嵌套路由点击

  • 跳转到子级路由方式三种:

    • 如果需要跳转到子级路由就需要 /home/news 方式

    • 或者直接写 ./news

    • 再或者直接写 news

<li>
  <NavLink className="list-group-item" to="./news">
    News
  </NavLink>
</li>
<li>
  {/* 如果需要跳转到子级路由就需要  `/home/news` 方式*/}
  <NavLink className="list-group-item" to="./message">
    Message
  </NavLink>
</li>

自己路由展示

需要引入Outlet

import { Outlet } from "react-router-dom";
{/* 指定路由组件呈现位置 */}
<Outlet />

06 路由传参-params参数

路由表中

注意路径书写格式:detail/:id/:title/:content

import { Navigate } from "react-router-dom";
import About from "../page/About";
import Home from "../page/Home";
import Message from "./../page/Message";
import News from "./../page/News";
import Detail from "../page/Detail";

export default [
  { path: "/about", element: <About /> },
  {
    path: "/home",
    element: <Home />,
    children: [
      {
        path: "message",
        element: <Message />,
        children: [{ path: "detail/:id/:title/:content", element: <Detail /> }],
      },
      { path: "news", element: <News /> },
    ],
  },
  { path: "/", element: <Navigate to="about" /> },
];

路由书写格式,要和传入时候一致,并且在接受时也需要一样

传参给子路由

  • 当点击这些标签时候会显示当前页面子路由中的内容
  • 需要将内容传递给子路由
  • 注意写入方式:to={detail/${item.id}/${item.title}/${item.content}
import React, { useState } from "react";
import { NavLink, Outlet } from "react-router-dom";

export default function Message() {
  const [messages] = useState([
    { id: "001", title: "消息1", content: "锄禾日当午" },
    { id: "002", title: "消息2", content: "汗滴禾下土" },
    { id: "003", title: "消息3", content: "谁知盘中餐" },
    { id: "004", title: "消息4", content: "粒粒皆辛苦" },
  ]);
  return (
    <div>
      <ul>
        {messages.map((item) => {
          return (
            <li key={item.id}>
              <NavLink to={`detail/${item.id}/${item.title}/${item.content}`}>
                {item.title}
              </NavLink>
            </li>
          );
        })}
      </ul>
      {/* 路由展示位置---子级路由 */}
      <Outlet />
    </div>
  );
}

注意写时:

<NavLink to={`detail/${item.id}/${item.title}/${item.content}`}>
	{item.title}
</NavLink>

接受参数

import React from "react";
import { useMatch, useParams } from "react-router-dom";

export default function Detail() {
  // `useParams` 使用的比较多
  // `useMatch` 用的不多,但是要知道下
  const { id, title, content } = useParams();
  const match = useMatch("/home/message/detail/:id/:title/:content");
  console.log(match);

  return (
    <ul>
      <li>
        消息的编号:{id},消息的标题:{title},消息的内容{content}
      </li>
      <li>
        消息的编号:{id},消息的标题:{title},消息的内容{content}
      </li>
      <li>
        消息的编号:{id},消息的标题:{title},消息的内容{content}
      </li>
    </ul>
  );
}

07 路由的search参数

路由表

import { Navigate } from "react-router-dom";
import About from "../page/About";
import Home from "../page/Home";
import Message from "./../page/Message";
import News from "./../page/News";
import Detail from "../page/Detail";

export default [
  { path: "/about", element: <About /> },
  {
    path: "/home",
    element: <Home />,
    children: [
      {
        path: "message",
        element: <Message />,
        children: [{ path: "detail", element: <Detail /> }],
      },
      { path: "news", element: <News /> },
    ],
  },
  { path: "/", element: <Navigate to="about" /> },
];

传入参数

import React, { useState } from "react";
import { NavLink, Outlet } from "react-router-dom";

export default function Message() {
  const [messages] = useState([
    { id: "001", title: "消息1", content: "锄禾日当午" },
    { id: "002", title: "消息2", content: "汗滴禾下土" },
    { id: "003", title: "消息3", content: "谁知盘中餐" },
    { id: "004", title: "消息4", content: "粒粒皆辛苦" },
  ]);
  return (
    <div>
      <ul>
        {messages.map((item) => {
          return (
            // 当点击这些标签时候会显示当前页面子路由中的内容
            // 需要将内容传递给子路由
            <li key={item.id}>
              <NavLink
                to={`detail?id=${item.id}&title=${item.title}&content=${item.content}`}
              >
                {item.title}
              </NavLink>
            </li>
          );
        })}
      </ul>
      <Outlet />
    </div>
  );
}

接受参数

  • setSearch 更新参数
  • search 通过get("传入需要的键")方法才能获取到想要的字段
import React from "react";
import { useSearchParams } from "react-router-dom";

export default function Detail() {

  const [search, setSearch] = useSearchParams();
  const id = search.get("id");
  const title = search.get("title");
  const content = search.get("content");
  return (
    <ul>
      <li>
        <button
          className="btn btn-success"
          onClick={() => setSearch("id=008&title=还好&content=嘻嘻")}
        >
          点我更新下search参数
        </button>
      </li>
      <li>{id}</li>
      <li>{title}</li>
      <li>{content}</li>
    </ul>
  );
}
const [search, setSearch] = useSearchParams();

// search 负责获取数据
// setSearch 负责更新数据
// 两个使用数组结构的

08 路由的state参数

路由表中

import { Navigate } from "react-router-dom";
import About from "../page/About";
import Home from "../page/Home";
import Message from "./../page/Message";
import News from "./../page/News";
import Detail from "../page/Detail";

export default [
  { path: "/about", element: <About /> },
  {
    path: "/home",
    element: <Home />,
    children: [
      {
        path: "message",
        element: <Message />,
        children: [{ path: "detail", element: <Detail /> }],
      },
      { path: "news", element: <News /> },
    ],
  },
  { path: "/", element: <Navigate to="about" /> },
];

传入参数

import React, { useState } from "react";
import { NavLink, Outlet } from "react-router-dom";

export default function Message() {
  const [messages] = useState([
    { id: "001", title: "消息1", content: "锄禾日当午" },
    { id: "002", title: "消息2", content: "汗滴禾下土" },
    { id: "003", title: "消息3", content: "谁知盘中餐" },
    { id: "004", title: "消息4", content: "粒粒皆辛苦" },
  ]);
  return (
    <div>
      <ul>
        {messages.map((item) => {
          return (
            // 当点击这些标签时候会显示当前页面子路由中的内容
            // 需要将内容传递给子路由
            <li key={item.id}>
              <NavLink
                to="detail"
                state={{
                  id: item.id,
                  title: item.title,
                  content: item.content,
                }}
              >
                {item.title}
              </NavLink>
            </li>
          );
        })}
      </ul>
      <Outlet />
    </div>
  );
}

接受参数

在接受参数时,和使用useState方式差不多

import { useLocation } from "react-router-dom";

export default function Detail() {
  const {
    state: { id, title, content },
  } = useLocation();

  return (
    <ul>
      <li>{id}</li>
      <li>{title}</li>
      <li>{content}</li>
    </ul>
  );
}

09 编程式路由导航

路由表中

import { Navigate } from "react-router-dom";
import About from "../page/About";
import Home from "../page/Home";
import Message from "./../page/Message";
import News from "./../page/News";
import Detail from "../page/Detail";

export default [
  { path: "/about", element: <About /> },
  {
    path: "/home",
    element: <Home />,
    children: [
      {
        path: "message",
        element: <Message />,
        children: [{ path: "detail", element: <Detail /> }],
      },
      { path: "news", element: <News /> },
    ],
  },
  { path: "/", element: <Navigate to="about" /> },
];

传入参数

  • 编程式路由导航
  • 可以实现路由跳转的功能
  • 如果后面传入的参数为 replacr:true 表示替换当前页面
  • navigate(-1) 表示后退
  • navigate(1) 表示前进
import React, { useState } from "react";
import { NavLink, Outlet, useNavigate } from "react-router-dom";

export default function Message() {
  const [messages] = useState([
    { id: "001", title: "消息1", content: "锄禾日当午" },
    { id: "002", title: "消息2", content: "汗滴禾下土" },
    { id: "003", title: "消息3", content: "谁知盘中餐" },
    { id: "004", title: "消息4", content: "粒粒皆辛苦" },
  ]);
  const navigate = useNavigate();
  const showDatail = (item: any) => {
    /**
     * 编程式路由导航
     * 可以实现路由跳转的功能
     * 如果后面传入的参数为 `replacr:true` 表示替换当前页面
     * navigate(-1) 表示后退
     * navigate(1) 表示前进
     */

    navigate("detail", {
      replace: true,
      state: {
        id: item.id,
        title: item.title,
        content: item.content,
      },
    });
  };
  return (
    <div>
      <ul>
        {messages.map((item) => {
          return (
            // 当点击这些标签时候会显示当前页面子路由中的内容
            // 需要将内容传递给子路由
            <li key={item.id}>
              <NavLink
                to="detail"
                state={{
                  id: item.id,
                  title: item.title,
                  content: item.content,
                }}
              >
                {item.title}
              </NavLink>
              <button
                className="btn btn-danger"
                onClick={() => showDatail(item)}
              >
                查看详情
              </button>
            </li>
          );
        })}
      </ul>
      <Outlet />
    </div>
  );
}

重点在:

  • 要使用navigate进行编程式路由导航
navigate("detail", {
  replace: true,
  state: {
    id: item.id,
    title: item.title,
    content: item.content,
  },
});

接受参数

import { useLocation } from "react-router-dom";

export default function Detail() {
  const {
    state: { id, title, content },
  } = useLocation();

  return (
    <ul>
      <li>{id}</li>
      <li>{title}</li>
      <li>{content}</li>
    </ul>
  );
}

10 路由上下文环境判断

  • 在路由中是否处于上下文环境中,可以使用useOutletContext

需要引入

import { useOutletContext } from "react-router-dom";

判断是否在上下文环境

// 只要被 `BrowserRouter` 包裹就代表是true
console.log(useOutletContext()); // true

11 返回当前导航类型

需要引入包useNavigationType

import { useOutletContext } from "react-router-dom";
// 返回当前导航类型(用户是怎么来到这个页面的)
console.log(useNavigationType());

12 呈现当前组件中嵌套路由

import { useOutletContext } from "react-router-dom";
// 呈现当前组件中嵌套路由
console.log(useOutlet());
### 实现 React 中的路由表重定向 为了实现在 `React` 应用程序中通过路由表进行页面重定向,在创建应用程序结构时需遵循特定模式。当构建基于 `react-router-dom` 的项目时,确保安装并引入了最新版本的相关包。 对于希望实现简单页面间重定向的情况,可以在定义路由规则的同时利用 `<Route>` 组件配合 `element` 或者 `render` 方法来完成操作[^2]: ```jsx import { Route, Routes, Navigate } from 'react-router-dom'; <Routes> <Route path="/old-path" element={<Navigate to="/new-path" />} /> </Routes> ``` 上述代码片段展示了如何将 `/old-path` 访问请求自动转向至 `/new-path` 页面。这里采用了 `Navigate` 组件替代旧版中的 `Redirect` 来达成目的,这是因为在 `react-router-dom v6` 版本之后推荐的方式[^4]。 如果是在更复杂的场景下处理嵌套或者多级子路径之间的跳转,则可能涉及到更加细致的设计思路。例如设置默认首页或者其他业务逻辑触发条件下的动态调整目标位置等情形。此时同样可以通过自定义匹配规则以及编程方式调用导航函数来进行控制[^5]。 另外值得注意的是,整个应用应当被 `BrowserRouter` 包裹以便于正常工作,这一步骤通常发生在项目的入口文件处,比如 `index.js` 文件里[^3]。 最后回到最初提到的例子——在 `App.js` 内部想要依据路由配置显示不同组件的情况下,除了正确加载路由映射外,还需注意保证上下文中存在有效的历史记录栈支持,这样才能让诸如前进后退按钮等功能按预期运作[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值