前端路由

前端路由一般通过HistoryAPI或是路径Hash实现,React没有内置前端路由相关的功能,但我们可以集成react-router这个库来实现,目前react-router最新版本是v6.4,新版本的一些API发生了变化,我们将以最新版本进行介绍。

安装React Router

执行以下命令安装react-router库。

npm install react-router-dom@6 --save

注意:我们安装的包名为react-router-dom,除此之外还有react-routerreact-router-native这两个包,但它们包含了React Native相关的支持,我们在浏览器环境中不需要使用,因此仅安装react-router-dom即可。

React Router基本使用

使用路由组件

react-router提供了如下几个基础组件用于构建路由:

BrowserRouter:BrowserRouter组件一般位于应用的最外层,它基于浏览器的HistoryAPI和React Context实现,提供了识别路由并改变其内部渲染组件的功能。

HashRouter:同BrowserRouter,但路由使用URL的Hash实现。

Route:Route用于定义访问路径和组件的关系,访问一个路径时,对应路径的组件会渲染出来。

Routes:Routes用于包裹若干个Route组件,它类似于switch...case...语句中switch的作用。

Link:Link的作用类似于<a>标签,用于实现跳转链接。实际上Link组件最终也会以<a>标签形式渲染,但它们的功能有些区别,react-router重写了它的默认逻辑,如果跳转的页面是Route路由中定义的,那么它只会改变页面上渲染的内容,而不会重新刷新页面。如果使用react-router,我们就应该尽量使用Link组件而不是<a>标签。

Redirect:前端路由重定向。重定向本身是后端的概念,指HTTP服务端返回301或302请求,告知客户端跳转到一个新的地址,Redirect组件的意义和Link组件类似,它能让前端路由重定向而不必请求服务端。

实际开发中,由于现代浏览器已经广泛支持HistoryAPI了,因此我们一般都选用BrowserRouter作为路由的实现方式。

下面例子代码中,我们使用BrowserRouter实现了前端路由,分别访问/a/b/c地址会分别渲染A、B、C三个组件。

index.js

import React from "react";
import ReactDOM from "react-dom/client";
import { BrowserRouter, Route, Routes } from "react-router-dom";
import ComponentA from "./ComponentA";
import ComponentB from "./ComponentB";
import ComponentC from "./ComponentC";

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
  <React.StrictMode>
    <BrowserRouter>
      <Routes>
        <Route path="/a" Component={ComponentA} />
        <Route path="/b" Component={ComponentB} />
        <Route path="/c" Component={ComponentC} />
      </Routes>
    </BrowserRouter>
  </React.StrictMode>
);

下面代码中,我们使用Link组件实现路由跳转,点击后会跳转到组件B,我们可以和<a>标签对比观察,Link组件跳转时页面是不会重新请求服务端加载的。

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

const ComponentA = () => {
  return (
    <div>
      <Link to="/b">ComponentB</Link>
    </div>
  );
};

export default ComponentA;

手动路由跳转

此外,我们也可以使用JavaScript代码进行手动跳转。React Router中手动跳转需要使用useNavigate(),这和原生客户端JavaScript中修改location.href不同。

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

const ComponentA = () => {
  const navigate = useNavigate();

  return (
    <div>
      <button
        onClick={() => {
          navigate("/b");
        }}
      >
        Button
      </button>
    </div>
  );
};

export default ComponentA;

404页面

实现404页面功能很简单,我们指定一个*路由,当其他路由都不匹配时就会渲染该路由指定的组件。

<BrowserRouter>
  <Routes>
    <Route path="/a" Component={ComponentA} />
    <Route path="/b" Component={ComponentB} />
    <Route path="/c" Component={ComponentC} />
    <Route path="*" Component={NotFound} />
  </Routes>
</BrowserRouter>;

代码中我们创建了一个NotFound组件,其他路由都不匹配时就会渲染该组件。

获取URL参数

react-router中提供了Hooks函数,用来获取GET参数和路径参数。

获取GET参数

对于URL中的GET参数(?后面的参数),我们可以使用useSearchParams进行解析。

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

const ComponentA = () => {
  const [searchParams] = useSearchParams();

  return (
    <div>
      {searchParams.get("username")}
      {searchParams.get("classId")}
    </div>
  );
};

export default ComponentA;

例子中我们获取了GET参数,并显示到页面上。

获取路径参数

路由路径中我们可以使用冒号定义路径参数的占位符,形如/a/:id,此时我们可以使用useParams获取真实的路径参数。注意这回影响路由的匹配,形如/a/3/a/tom会匹配/a/:id,但/a不会。如果希望参数的可选的,可以使用/a/:id?的形式定义可选路径参数。

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

const ComponentA = () => {
  const { id } = useParams();

  return <div>{id}</div>;
};

export default ComponentA;

上面例子代码中我们获取了请求的路径参数并显示到页面上。

获取全路径信息

useLocation可以解析整个路径信息,如果前面的几种取参数方式不能满足,我们也可以通过useLocation手动解析参数。一个location对象的例子(这里用的是BrowserRouter进行演示):

{
  hash: "";
  key: "jnvqdg";
  pathname: "/a";
  search: "";
  state: undefined;
}
  • hash:路由#后面的值
  • key:一个随机值,location对象的逻辑主键
  • pathname:当前路径
  • search:查询参数,就是?后面的字符串
  • state:路由可携带的载荷
import { useLocation } from "react-router-dom";

const ComponentA = () => {
  const { pathname, search, hash } = useLocation();

  return (
    <div>
      {pathname}
      {search}
      {hash}
    </div>
  );
};

export default ComponentA;

上面例子代码中,我们从当前路径中解析出了pathnamesearchhash的值。

作者:Gacfox
版权声明:本网站为非盈利性质,文章如非特殊说明均为原创,版权遵循知识共享协议CC BY-NC-ND 4.0进行授权,转载必须署名,禁止用于商业目的或演绎修改后转载。
Copyright © 2017-2024 Gacfox All Rights Reserved.
Build with NextJS | Sitemap