React 第八章 React-router v6

React-router v6

前端路由概念

前端路由是指在单页面应用中,通过改变 URL 来改变页面内容的一种技术。

早期的时候并不存在前端路由,那个时候只有后端路由,类似于下图:

每次点击链接或者提交表单都会向服务器发送请求,服务器返回新的 HTML 页面,然后浏览器重新加载整个页面。

后来,随着单页应用的流行,整个 Web 应用之存在一个页面,通过 JS 调整模块来显示不同的内容,类似于下图:

在单页面应用中,页面只加载一次,所有的操作都是在页面上动态加载内容并改变 URL。所谓前端路由实际上就是协调当前页面显示什么模块。

那么单页应用时代,还存在后端路由么?

实际上也是存在的,后端路由负责返回对应的数据,如下图:

后端路由主要用于处理URL的请求,将不同的URL请求映射到不同的逻辑处理函数上。在单页面应用中,后端路由可以用于实现以下功能:

  1. 服务器端渲染:单页面应用通常是在浏览器端通过JavaScript动态地生成页面内容。但是,有些情况下需要在服务器端生成页面内容,例如搜索引擎的爬虫需要获取完整的页面内容进行索引。后端路由可以用于将URL请求映射到服务器端的渲染函数上,从而在服务器端生成页面内容。

  2. 数据预取:单页面应用通常需要从服务器端获取数据,并在页面加载完成后显示。后端路由可以用于将URL请求映射到服务器端的数据获取函数上,从而在页面加载之前就预先获取数据。

  3. 服务端认证和权限控制:在单页面应用中,用户认证和权限控制通常是由服务器端处理的。后端路由可以用于将URL请求映射到服务器端的认证和权限控制函数上,从而对用户进行认证和权限验证。

  4. URL参数处理:在单页面应用中,通常需要从URL中获取参数,例如页面的过滤条件、排序方式等。后端路由可以用于将URL请求映射到服务器端的参数处理函数上,从而解析URL参数并进行相应的处理。

React-router

React-routerReact 官方所推出的前端路由库,官网地址:https://reactrouter.com/en/main

目前最新的版本为 v6 版本。相比之前的版本,该版本变化略大,加入了许多新的 Hook ,比如 useRoutes 这个 Hook 就提供了类似于 Vue-router 相似的特性,从而使得使用起来更加的方便。

整个官网可以分为几大块:

  • Components 组件
  • Hooks 函数
  • API 函数

为了更好更快的了解使用react-router,我们将按照功能讲解。本章节不会包含全部的API,更多的使用方法参考官网

不同的历史模式

Hash 模式

hash路由(hash-based routing)是一种在URL中使用哈希(#)来实现路由的方式。

hash 路由可以使用以下方式创建的:

  1. createHashRouter API
  2. HashRouter component

createHashRouter API

createHashRouter API 类似于 vue-router v4 创建路由的方式。在函数调用时,可以将项目中的路由配置好。

createHashRouter 返回值不能直接渲染,需要通过 RouterProvider 渲染

以下是关于两种方式的使用实例:

javascript 复制代码
import * as React from "react";
import * as ReactDOM from "react-dom";
import {
  createHashRouter,
  RouterProvider,
} from "react-router-dom";

import Root, { rootLoader } from "./routes/root";
import Team, { teamLoader } from "./routes/team";

const router = createHashRouter([
  {
    path: "/",
    element: <Root />,
    loader: rootLoader,
    children: [
      {
        path: "team",
        element: <Team />,
        loader: teamLoader,
      },
    ],
  },
]);

ReactDOM.createRoot(document.getElementById("root")).render(
  <RouterProvider router={router} />
);

HashRouter component

以HashRouter方式创建 hash 路由, 需要在根组件 App 外面包一层 HashRouter 组件

javascript 复制代码
import * as React from "react";
import * as ReactDOM from "react-dom";
import { HashRouter } from "react-router-dom";

ReactDOM.render(
  <HashRouter>
    <App />
  </HashRouter>,
  root
);

HTML5 模式

HTML5 模式的路由是一种网页导航方式,它使用 HTML5 History API 来实现无刷新的页面跳转和状态管理。

HTML5 模式的路由使用普通的 URL,例如 https://example.com/about,这样的 URL 更加友好和直观。当用户点击网页中的链接时,浏览器不会刷新整个页面,而是通过 JavaScript 监听 URL 的变化,并根据新的 URL 加载对应的页面内容。

HTML5 模式可以通过以下方式创建

  1. createBrowserRouter Api
  2. BrowserRouter component

以下是关于两种方式的使用实例:

createBrowserRouter Api

javascript 复制代码
import * as React from "react";
import * as ReactDOM from "react-dom";
import {
  createBrowserRouter,
  RouterProvider,
} from "react-router-dom";

import Root, { rootLoader } from "./routes/root";
import Team, { teamLoader } from "./routes/team";

const router = createBrowserRouter([
  {
    path: "/",
    element: <Root />,
    loader: rootLoader,
    children: [
      {
        path: "team",
        element: <Team />,
        loader: teamLoader,
      },
    ],
  },
]);

ReactDOM.createRoot(document.getElementById("root")).render(
  <RouterProvider router={router} />
);

BrowserRouter component

javascript 复制代码
import * as React from "react";
import { createRoot } from "react-dom/client";
import { BrowserRouter } from "react-router-dom";

const root = createRoot(document.getElementById("root"));

root.render(
  <BrowserRouter>
    {/* The rest of your app goes here */}
  </BrowserRouter>
);

如何配置路由

  • 通过 createHashRouter Api 或者 createBrowserRouter Api 创建的路由模式,可以在 Api 使用时,直接配置。例如:
javascript 复制代码
const router = createBrowserRouter([
  {
    path: "/",
    element: <Root />,
    loader: rootLoader,
    children: [
      {
        path: "team",
        element: <Team />,
        loader: teamLoader,
      },
    ],
  },
]);
  • 通过 HashRouter component 或者 BrowserRouter component 方式创建的路由可以通过 Routes 组件 或者 useRoutes 配置。例如:

Routes

javascript 复制代码
<Routes>
  <Route path="/" element={<Dashboard />}>
    <Route
      path="messages"
      element={<DashboardMessages />}
    />
    <Route path="tasks" element={<DashboardTasks />} />
  </Route>
  <Route path="about" element={<AboutPage />} />
</Routes>

useRoutes

javascript 复制代码
import * as React from "react";
import { useRoutes } from "react-router-dom";

function App() {
  let element = useRoutes([
    {
      path: "/",
      element: <Dashboard />,
      children: [
        {
          path: "messages",
          element: <DashboardMessages />,
        },
        { path: "tasks", element: <DashboardTasks /> },
      ],
    },
    { path: "team", element: <AboutPage /> },
  ]);

  return element;
}

嵌套路由

一些应用程序的 UI 由多层嵌套的组件组成。在这种情况下,URL 的片段通常对应于特定的嵌套组件结构,例如:

javascript 复制代码
const router = createBrowserRouter([
  {
    path: "/",
    element: <Root />,
    loader: rootLoader,
    children: [
      {
        path: "team",
        element: <Team />,
        loader: teamLoader,
      },
    ],
  },
]);

url /teamurl / 的子路由,如果想要 Root 组件中显示 子路由的内容,需要在 Root 组件中 使用 Outlet, 例如:

javascript 复制代码
function Root() {
	return (
		<Outlet />
	)
}

声明式导航

声明式导航有以下几种方式

在 React Router v6 中,你可以使用以下几种方式进行声明式导航:

  1. 使用 <Link> 组件:<Link> 组件是 React Router 提供的一种声明式导航方式。你可以在应用中的任何地方使用它,通过设置 to 属性指定导航目标。例如:
jsx 复制代码
import { Link } from 'react-router-dom';

function MyComponent() {
  return (
    <div>
      <Link to="/home">Home</Link>
      <Link to="/about">About</Link>
    </div>
  );
}
  1. 使用 <NavLink> 组件:<NavLink> 组件是 <Link> 的扩展版本,它支持在当前路径匹配时添加特定的样式或类名。可以使用 activeClassNameactiveStyle 属性设置当前活动路径的样式。例如:
jsx 复制代码
import { NavLink } from 'react-router-dom';

function MyComponent() {
  return (
    <div>
      <NavLink to="/home" activeClassName="active">Home</NavLink>
      <NavLink to="/about" activeClassName="active">About</NavLink>
    </div>
  );
}
  1. 使用 useNavigate 钩子:React Router v6 引入了新的 hook useNavigate,它返回一个可用于导航的函数。你可以在组件中使用 useNavigate 钩子,然后在需要导航的地方调用它。例如:
jsx 复制代码
import { useNavigate } from 'react-router-dom';

function MyComponent() {
  const navigate = useNavigate();

  const handleClick = () => {
    navigate('/home');
  }

  return (
    <div>
      <button onClick={handleClick}>Go to Home</button>
    </div>
  );
}

这些是 React Router v6 中的几种声明式导航方式。你可以根据项目需求选择适合你的方式。在 React Router v6 中,你可以使用以下几种方式进行声明式导航:

  1. 使用 <Link> 组件:<Link> 组件是 React Router 提供的一种声明式导航方式。你可以在应用中的任何地方使用它,通过设置 to 属性指定导航目标。例如:
jsx 复制代码
import { Link } from 'react-router-dom';

function MyComponent() {
  return (
    <div>
      <Link to="/home">Home</Link>
      <Link to="/about">About</Link>
    </div>
  );
}
  1. 使用 <NavLink> 组件:<NavLink> 组件是 <Link> 的扩展版本,它支持在当前路径匹配时添加特定的样式或类名。可以使用 activeClassNameactiveStyle 属性设置当前活动路径的样式。例如:
jsx 复制代码
import { NavLink } from 'react-router-dom';

function MyComponent() {
  return (
    <div>
      <NavLink to="/home" activeClassName="active">Home</NavLink>
      <NavLink to="/about" activeClassName="active">About</NavLink>
    </div>
  );
}
  1. 使用 useNavigate 钩子:React Router v6 引入了新的 hook useNavigate,它返回一个可用于导航的函数。你可以在组件中使用 useNavigate 钩子,然后在需要导航的地方调用它。例如:
jsx 复制代码
import { useNavigate } from 'react-router-dom';

function MyComponent() {
  const navigate = useNavigate();

  const handleClick = () => {
    navigate('/home');
  }

  return (
    <div>
      <button onClick={handleClick}>Go to Home</button>
    </div>
  );
}

这些是 React Router v6 中的几种声明式导航方式。你可以根据项目需求选择适合你的方式。在 React Router v6 中,你可以使用以下几种方式进行声明式导航:

  1. 使用 <Link> 组件:<Link> 组件是 React Router 提供的一种声明式导航方式。你可以在应用中的任何地方使用它,通过设置 to 属性指定导航目标。例如:
jsx 复制代码
import { Link } from 'react-router-dom';

function MyComponent() {
  return (
    <div>
      <Link to="/home">Home</Link>
      <Link to="/about">About</Link>
    </div>
  );
}
  1. 使用 <NavLink> 组件:<NavLink> 组件是 <Link> 的扩展版本,它支持在当前路径匹配时添加特定的样式或类名。可以使用 activeClassNameactiveStyle 属性设置当前活动路径的样式。例如:
jsx 复制代码
import { NavLink } from 'react-router-dom';

function MyComponent() {
  return (
    <div>
      <NavLink to="/home" activeClassName="active">Home</NavLink>
      <NavLink to="/about" activeClassName="active">About</NavLink>
    </div>
  );
}
  1. 使用 useNavigate 钩子:React Router v6 引入了新的 hook useNavigate,它返回一个可用于导航的函数。你可以在组件中使用 useNavigate 钩子,然后在需要导航的地方调用它。例如:
jsx 复制代码
import { useNavigate } from 'react-router-dom';

function MyComponent() {
  const navigate = useNavigate();

  const handleClick = () => {
    navigate('/home');
  }

  return (
    <div>
      <button onClick={handleClick}>Go to Home</button>
    </div>
  );
}

这些是 React Router v6 中的几种声明式导航方式。你可以根据项目需求选择适合你的方式。在 React Router v6 中,你可以使用以下几种方式进行声明式导航:

  1. 使用 <Link> 组件:<Link> 组件是 React Router 提供的一种声明式导航方式。你可以在应用中的任何地方使用它,通过设置 to 属性指定导航目标。例如:
jsx 复制代码
import { Link } from 'react-router-dom';

function MyComponent() {
  return (
    <div>
      <Link to="/home">Home</Link>
      <Link to="/about">About</Link>
    </div>
  );
}
  1. 使用 <NavLink> 组件:<NavLink> 组件是 <Link> 的扩展版本,它支持在当前路径匹配时添加特定的样式或类名。可以使用 activeClassNameactiveStyle 属性设置当前活动路径的样式。例如:
jsx 复制代码
import { NavLink } from 'react-router-dom';

function MyComponent() {
  return (
    <div>
      <NavLink to="/home" activeClassName="active">Home</NavLink>
      <NavLink to="/about" activeClassName="active">About</NavLink>
    </div>
  );
}

编程式导航

使用 useNavigate Hook, 返回值是一个函数 可以接收两个参数navigate(参数一, 参数二)

  • 参数一: 可以是 url 或者在历史堆栈中传递您想要的增量,例如返回上一页 navigate(-1), 例如:
javascript 复制代码
import { useNavigate } from 'react-router-dom';

const navigate = useNavigate();

// 在点击或触发某个事件时进行导航
const handleNavigation = () => {
  navigate('/path');
}

// 返回上一页
const backPage = () => {
	navigate(-1)
}
  • 参数二: 是一个配置项 options,有以下配置
  1. options.replace: replace: true将导致导航替换历史堆栈中的当前url
  2. options.state: 包含一个可选的状态值来存储在历史状态中,然后可以通过useLocation在目标路由上访问它。例如:
javascript 复制代码
navigate("/new-route", { state: { key: "value" } });
  1. 更多用法参考官网

路由重定向

重定向也是通过 routes 配置来完成,下面例子是从 /home 重定向到 /:

javascript 复制代码
import {Navigate} from "react-router-dom";

{ path: "/home", element: <Navigate to="/" />}

动态路由匹配

如果一个路径段以:开头,那么它就变成了一个"动态段"。当路由匹配URL时,动态段将从URL中解析出来,并作为参数提供给其他路由器api。例如:

javascript 复制代码
{ path: "/user:id", element: <User />}

如何获取动态段的信息,可以通过 useParams() 获取, 例如:

javascript 复制代码
function User() {
  const { id } = useParams();
}

路由懒加载

当打包构建应用时,JavaScript 包会变得非常大,影响页面加载。如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样就会更加高效。例如:

javascript 复制代码
const router = createBrowserRouter([
  {
    path: "/",
    element: <Root />,
    children: [
      {
        path: '',
        lazy: () => import('./Page1'),
      },
      {
        path: "team",
        lazy: () => import('./Page2')
      },
    ],
  },
]);
相关推荐
彭世瑜4 分钟前
ts: TypeScript跳过检查/忽略类型检查
前端·javascript·typescript
FØund4045 分钟前
antd form.setFieldsValue问题总结
前端·react.js·typescript·html
Backstroke fish5 分钟前
Token刷新机制
前端·javascript·vue.js·typescript·vue
小五Five7 分钟前
TypeScript项目中Axios的封装
开发语言·前端·javascript
小曲程序7 分钟前
vue3 封装request请求
java·前端·typescript·vue
临枫5417 分钟前
Nuxt3封装网络请求 useFetch & $fetch
前端·javascript·vue.js·typescript
前端每日三省9 分钟前
面试题-TS(八):什么是装饰器(decorators)?如何在 TypeScript 中使用它们?
开发语言·前端·javascript
小刺猬_9859 分钟前
(超详细)数组方法 ——— splice( )
前端·javascript·typescript
渊兮兮10 分钟前
Vue3 + TypeScript +动画,实现动态登陆页面
前端·javascript·css·typescript·动画
鑫宝Code11 分钟前
【TS】TypeScript中的接口(Interface):对象类型的强大工具
前端·javascript·typescript