react-router-dom v6 使用详细示例

目录
  • 一、基本使用
  • 二、路由跳转
    • 2.1 Link 组件
    • 2.2 NavLink 组件
    • 2.3 编程式跳转
  • 三、动态路由参数
    • 3.1 路径参数
      • 路径匹配规则
      • 兼容类组件
    • 3.2 search 参数
  • 四、嵌套路由
    • 5.1 路由定义
    • 5.2 在父组件中展示
    • 5.3 在组件中定义
  • 五、默认路由
  • 六、全匹配路由
  • 七、多组路由
  • 八、路由重定向
  • 九、布局路由
  • 十、订阅和操作 history stack的原理
    • 10.1 History对象
    • 11.2 Location对象
      • state
      • key
  • 十一、 各类Router组件
    • 11.1 HashRouter和BrowserRouter的区别
    • 11.2 unstable_HistoryRouter
    • 11.3 MemoryRouter
    • 11.4 NativeRouter
    • 11.5 StaticRouter
  • 十二、使用JS对象定义路由:useRoutes

一、基本使用

首先安装依赖:

npm i react-router-dom

引入实现路由所需的组件,以及页面组件:

import { BrowserRouter, Routes, Route } from "react-router-dom";
import Foo from "./Foo";
import Bar from "./Bar";
function App() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/foo" element={<Foo />} />
        <Route path="/bar" element={<Bar />} />
      </Routes>
    </BrowserRouter>
  );
}
  • path:路径
  • element:要渲染的组件

注意BrowserRouter组件最好放在最顶层所有组件之外,这样能确保内部组件使用 Link 做路由跳转时不出错

二、路由跳转

在跳转路由时,如果路径是/开头的则是绝对路由,否则为相对路由,即相对于当前 URL进行改变

2.1 Link 组件

Link组件只能在Router内部使用,因此使用到Link组件的组件一定要放在顶层的 Router 之内

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

<Link to="foo">to foo</Link>;

2.2 NavLink 组件

  • NavLink组件Link组件的功能是一致的,区别在于可以判断其to属性是否是当前匹配到的路由
  • NavLink组件styleclassName可以接收一个函数,函数接收一个含有isActive字段的对象为参数,可根据该参数调整样式
import { NavLink } from "react-router-dom";

function Foo() {
  return (
    <NavLink style={({ isActive }) => ({ color: isActive ? "red" : "#fff" })}>
      Click here
    </NavLink>
  );
}

2.3 编程式跳转

使用useNavigate钩子函数生成navigate函数,可以通过 JS 代码完成路由跳转

useNavigate取代了原先版本中的useHistory

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

function Foo(){
    const navigate = useNavigate();
    return (
        // 上一个路径:/a;    当前路径: /a/a1
        <div onClick={() => navigate('/b')}>跳转到/b</div>
        <div onClick={() => navigate('a11')}>跳转到/a/a1/a11</div>
        <div onClick={() => navigate('../a2')}>跳转到/a/a2</div>
        <div onClick={() => navigate(-1)}>跳转到/a</div>
    )
}
  • 可以直接传入要跳转的目标路由(可以使用相对路径,语法和 JS 相同)
  • 传入-1表示后退

三、动态路由参数

3.1 路径参数

  • Route组件中的path属性中定义路径参数
  • 在组件内通过useParams hook 访问路径参数
<BrowserRouter>
  <Routes>
    <Route path="/foo/:id" element={<Foo />} />
  </Routes>
</BrowserRouter>;

import { useParams } from "react-router-dom";
export default function Foo() {
  const params = useParams();
  return (
    <div>
      <h1>{params.id}</h1>
    </div>
  );
}

路径匹配规则

当URL同时匹配到含有路径参数的路径和无参数路径时,有限匹配没有参数的”具体的“(specific)路径。

<Route path="teams/:teamId" element={<Team />} />
<Route path="teams/new" element={<NewTeamForm />} />

如上的两个路径,将会匹配 teams/new 。

路径的正则匹配已被移除。

兼容类组件

在以前版本中,组件的props会包含一个match对象,在其中可以取到路径参数。

但在最新的 6.x 版本中,无法从 props 获取参数。

并且,针对类组件的 withRouter 高阶组件已被移除。因此对于类组件来说,使用参数有两种兼容方法:

  • 将类组件改写为函数组件
  • 自己写一个 HOC 来包裹类组件,用 useParams 获取参数后通过 props 传入原本的类组件

3.2 search 参数

  • 查询参数不需要在路由中定义
  • 使用 useSearchParams hook 来访问和修改查询参数。其用法和 useState 类似,会返回当前对象和更改它的方法
  • 使用 setSearchParams 时,必须传入所有的查询参数,否则会覆盖已有参数
import { useSearchParams } from "react-router-dom";

// 当前路径为 /foo?id=12
function Foo() {
  const [searchParams, setSearchParams] = useSearchParams();
  console.log(searchParams.get("id")); // 12
  setSearchParams({
    name: "foo",
  }); // /foo?name=foo
  return <div>foo</div>;
}

四、嵌套路由

5.1 路由定义

通过嵌套的书写Route组件实现对嵌套路由的定义。

path 开头为 / 的为绝对路径,反之为相对路径。

<Routes>
  <Route path="/" element={<Home />}></Route>
  <Route path="/father" element={<Father />}>
    <Route path="child" element={<Child />}></Route>
    <Route path=":name" element={<Another />}></Route>
  </Route>
</Routes>

5.2 在父组件中展示

在父组件中使用Outlet来显示匹配到的子组件

import { Outlet } from "react-router-dom";
function Father() {
  return (
    <div>
      // ... 自己组件的内容 // 留给子组件Child的出口
      <Outlet />
    </div>
  );
}

5.3 在组件中定义

可以在任何组件中使用 Routes 组件,且组件内的Routes中,路径默认带上当前组件的路径作为前缀。

注意:此时定义父组件的路由时,要在后面加上 /* ,否则父组件将无法渲染。

<Routes>
  <Route path="/" element={<Home />} />
  <Route path="dashboard/*" element={<Dashboard />} />
</Routes>
function Dashboard() {
  return (
    <div>
      <p>Look, more routes!</p>
      <Routes>
        <Route path="/" element={<DashboardGraphs />} />
        <Route path="invoices" element={<InvoiceList />} />
      </Routes>
    </div>
  );
}

五、默认路由

定义: 在嵌套路由中,如果 URL 仅匹配了父级 URL,则Outlet中会显示带有index属性的子路由。可以使用在路由的任何层级

<Routes>
  <Route path="/foo" element={Foo}>
    <Route index element={Default}></Route>
    <Route path="bar" element={Bar}></Route>
  </Route>
</Routes>
  • 当 url 为/foo时:Foo 中的 Outlet 会显示 Default 组件
  • 当 url 为/foo/bar时:Foo 中的 Outlet 会显示为 Bar 组件

六、全匹配路由

定义:  path属性取值为*时,可以匹配任何(非空)路径,该匹配拥有最低的优先级。可以用于设置 404 页面。

<Routes>
  <Route path="/foo" element={Foo}>
    <Route path="bar" element={Bar}></Route>
    <Route path="*" element={NotFound}></Route>
  </Route>
</Routes>

七、多组路由

通常,一个应用中只有一个Routes组件。

但根据实际需要也可以定义多个路由出口(如:侧边栏和主页面都要随 URL 而变化)

<Router>
  <SideBar>
    <Routes>
      <Route></Route>
    </Routes>
  </SideBar>
  <Main>
    <Routes>
      <Route></Route>
    </Routes>
  </Main>
</Router>

八、路由重定向

当在某个路径/a下,要重定向到路径/b时,可以通过Navigate组件进行重定向到其他路径

等价于以前版本中的Redirect组件

import { Navigate } from "react-router-dom";
function A() {
  return <Navigate to="/b" />;
}

九、布局路由

当多个路由有共同的父级组件时,可以将父组件提取为一个没有 path 和 index 属性的Route组件(Layout Route)

<Route element={<PageLayout />}>
    <Route path="/privacy" element={<Privacy />} />
    <Route path="/tos" element={<Tos />} />
  </Route>

这种写法等价于:

<Route
  path="/privacy"
  element={
    <PageLayout>
      <Privacy />
    </PageLayout>
  }
/>
<Route
  path="/tos"
  element={
    <PageLayout>
      <Tos />
    </PageLayout>
  }
/>

十、订阅和操作 history stack的原理

浏览器会记录导航堆栈,以实现浏览器中的前进后退功能。在传统的前端项目中,URL的改变意味着向服务器重新请求数据。

在现在的客户端路由( client side routing )中,可以做到编程控制URL改变后的反应。如在点击a标签的回调函数中使用 event.preventDefault() 阻止默认事件,此时URL的改变不会带来任何UI上的更新。

<a
  href="/contact" rel="external nofollow"
  onClick={(event) => {
    // stop the browser from changing the URL and requesting the new document
    event.preventDefault();
    // push an entry into the browser history stack and change the URL
    window.history.pushState({}, undefined, "/contact");
  }}
/>

10.1 History对象

浏览器没有直接提供监听URL改变(push、pop、replace)的接口,因此 react-router 对原生的 history 对线进行了包装,提供了监听URL改变的API。

let history = createBrowserHistory();
history.listen(({ location, action }) => {
  // this is called whenever new locations come in
  // the action is POP, PUSH, or REPLACE
});

使用 react-router 时不需操作History对象(Routes 组件会进行操作)

11.2 Location对象

react-router 对 window.location 进行包装后,提供了一个形式简洁的Location对象,形如:

{
  pathname: "/bbq/pig-pickins",     // 主机名之后的URL地址
  search: "?campaign=instagram",    // 查询参数
  hash: "#menu",                    // 哈希值,用于确定页面滚动的具体位置
  state: null,                      // 对于 window.history.state 的包装
  key: "aefz24ie"                   //
}

state

不显示在页面上,不会引起刷新,只由开发人员操作。

可用于记录用户的跳转详情(从哪跳到当前页面)或在跳转时携带信息。

可以用在 Link 组件或 navigate 方法中

&lt;Link to="/pins/123" state={{ fromDashboard: true }} /&gt;
let navigate = useNavigate();
navigate("/users/123", { state: partialUser });
复制代码

在目标的组件中,可以用 useLocation 方法获取该对象

let location = useLocation();
console.log(location.state);

state中的信息会进行序列化,因此如日期对象等信息会变为string

key

每个Location对象拥有一个唯一的key,可以据此来实现基于Location的滚动管理,或是数据缓存。

如:将 location.key 和 URL 作为键,每次请求数据前,先查找缓存是否存在来判断是否实际发送请求,来实现客户端数据缓存。

十一、 各类Router组件

11.1 HashRouter和BrowserRouter的区别

  • HashRouter 只会修改URL中的哈希值部分;而 BrowserRouter 修改的是URL本身
  • HashRouter 是纯前端路由,可以通过输入URL直接访问;使用时 BrowserRouter 直接输入URL会显示404,除非配置Nginx将请求指向对应的HTML文件。初次进入 / 路径时或点击 Link 组件跳转时不会发送请求

11.2 unstable_HistoryRouter

使用 unstable_HistoryRouter 需要传入一个 history 库的实例,这将允许在非react作用于下操作history对象。

由于项目使用的history和react-router中使用的history版本可能不一样,该API目前标为unstable状态

11.3 MemoryRouter

HashRouter 和 BrowserRouter 都是依据外部对象(history)进行导航,而 MemoryRouter 则是自己存储和管理状态堆栈,多用于测试场景。

11.4 NativeRouter

推荐的用于 React Native的Router组件

11.5 StaticRouter

在nodejs端使用,渲染react应用。

import * as React from "react";
import * as ReactDOMServer from "react-dom/server";
import { StaticRouter } from "react-router-dom/server";
import http from "http";

function requestHandler(req, res) {
  let html = ReactDOMServer.renderToString(
    <StaticRouter location={req.url}>
      {/* The rest of your app goes here */}
    </StaticRouter>
  );

  res.write(html);
  res.end();
}

http.createServer(requestHandler).listen(3000);

十二、使用JS对象定义路由:useRoutes

使用 useRoutes hook,可以使用一个JS对象而不是Routes组件与Route组件来定义路由。其功能类似于react-router-config

useRoutes 的返回是 React Element,或是 null。

对于传入的配置对象, 其类型定义如下:

interface RouteObject {
    caseSensitive?: boolean;
    children?: RouteObject[];
    element?: React.ReactNode;
    index?: boolean;
    path?: string;
}

到此这篇关于react-router-dom v6 使用详细示例的文章就介绍到这了,更多相关react-router-dom v6 内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • react-router-domV6版本的路由和嵌套路由写法详解

    目录 1-单级路由 2-嵌套路由(about路径进行嵌套) ReactRouterv6使用路由嵌套和重定向 1 - 单级路由 <NavLink to="/home">Home</NavLink> <NavLink to="/about">about</NavLink> <Routes>   <Route path='/home' element={<Home/>}/>   <R

  • react-router-dom V6的配置使用实践

    目录 一.关于书写方面 二.路由的嵌套方面优化 三.关于路由的灵活配置化 四.关于路由鉴权方面 最近在搭建PC项目的React框架,涉及到React Router,开发同学有时就需要去尝试点新的东西,在开发过程中才不会枯燥的,基于这个理念推动,就在搭建的时候用V6的版本开始了(虽然只是个新版本,也不算啥新东西)...... V6的版本相对于V5,做了很多的优化,有书写方面的.路由的嵌套.路由配置化.鉴权方面等等,下面就简单的介绍下如何使用 一.关于书写方面 路由注册的时候由的Switch改为了R

  • 详解react-router-dom v6版本基本使用介绍

    目录 Routes Route Navigate NavLink useRoutes 嵌套路由 路由传参 编程式导航 Routes 代替Switch组件,不会向下匹配 用来包裹Route Route 必须被Routes组件包裹 component属性变成element caseSensitive 路径大小写敏感属性,默认是不敏感(访问/about = /ABOUT) index 与path属性是互斥的,index表示为当前路由的根 可以用作layout组件,不写element属性,写了要与 Ou

  • react-router-dom v6 通过outlet实现keepAlive 功能的实现

    本文主要介绍了react-router-dom v6 通过outlet实现keepAlive 功能的实现,具体如下: keepAlive代码: import React, { useRef, useEffect, useReducer, useMemo, memo } from 'react' import { TransitionGroup, CSSTransition } from 'react-transition-group' import { useLocation } from 'r

  • react-router-dom v6 使用详细示例

    目录 一.基本使用 二.路由跳转 2.1 Link 组件 2.2 NavLink 组件 2.3 编程式跳转 三.动态路由参数 3.1 路径参数 路径匹配规则 兼容类组件 3.2 search 参数 四.嵌套路由 5.1 路由定义 5.2 在父组件中展示 5.3 在组件中定义 五.默认路由 六.全匹配路由 七.多组路由 八.路由重定向 九.布局路由 十.订阅和操作 history stack的原理 10.1 History对象 11.2 Location对象 state key 十一. 各类Rou

  • React前端DOM常见Hook封装示例上

    目录 引言 useEventListener useClickAway useEventTarget useTitle useFavicon 引言 本文是深入浅出 ahooks 源码系列文章的第十四篇,这个系列的目标主要有以下几点: 加深对 React hooks 的理解. 学习如何抽象自定义 hooks.构建属于自己的 React hooks 工具库. 培养阅读学习源码的习惯,工具库是一个对源码阅读不错的选择. 上一篇我们探讨了 ahooks 对 DOM 类 Hooks 使用规范,以及源码中是

  • React前端DOM常见Hook封装示例下

    目录 引言 useFullscreen useHover useDocumentVisibility 引言 本文是深入浅出 ahooks 源码系列文章的第十五篇,这个系列的目标主要有以下几点: 加深对 React hooks 的理解. 学习如何抽象自定义 hooks.构建属于自己的 React hooks 工具库. 培养阅读学习源码的习惯,工具库是一个对源码阅读不错的选择. 上文指路:React前端DOM常见Hook封装示例上 本篇接着针对关于 DOM 的各个 Hook 封装进行解读. useF

  • React Router V6更新内容详解

    目录 ReactRouterV6变更介绍 1.<Switch>重命名为<Routes> 2.<Route>的新特性变更 3.嵌套路由变得更简单 3.1具体变化有以下: 3.2废弃了V5中的Redirect 3.3多个<Routes/> 4.用useNavigate代替useHistory 5.Hooks中新钩子useRoutes代替react-router-config 总结 React Router V6 变更介绍 之前一直在用5.x版本的Router,突

  • 使用React Router v6 添加身份验证的方法

    目录 开始 基础路由 创建受保护的路由 使用嵌套路由和< Outlet /> 结尾 React Router v6是React应用程序的一个流行且功能强大的路由库.它提供了一种声明式的.基于组件的路由方法,并能处理URL参数.重定向和加载数据等常见任务. 这个最新版本的React Router引入了很多新概念,比如<Outlet />和layout布局路由,但相关文档仍然很少. 本文将演示如何使用React Router v6创建受保护的路由以及如何添加身份验证. 开始 打开终端,

  • React Router v4 入坑指南(小结)

    距离React Router v4 正式发布也已经过去三个月了,这周把一个React的架子做了升级,之前的路由用的还是v2.7.0版的,所以决定把路由也升级下,正好"尝尝鲜"... 江湖传言,目前官方同时维护 2.x 和 4.x 两个版本.(ヾ(。ꏿ﹏ꏿ)ノ゙咦,此刻相信机智如我的你也会发现,ReactRouter v3 去哪儿了?整丢了??巴拉出锅了???敢不敢给我个完美的解释!?)事实上 3.x 版本相比于 2.x 并没有引入任何新的特性,只是将 2.x 版本中部分废弃 API 的

  • React 模式之纯组件使用示例详解

    目录 什么是纯组件 纯组件解决了什么问题 怎么使用纯组件 CC: shouldComponentUpdate() 和 React.PureComponent FC: React.memo() 你可能并不需要纯组件 什么是纯组件 纯组件(Pure Component)这概念衍生自纯函数.纯函数指的是返回结果只依赖于传入的参数,且对函数作用域外没有副作用的函数.这种函数在相同参数下,返回结果是不变的.纯函数的返回值能被安全地缓存起来,在下次调用时,跳过函数执行,直接读取缓存.因为函数没有外部副作用,

  • react 组件实现无缝轮播示例详解

    目录 正文 无缝轮播 实现思路 构思使用时代码结构 Carousel组件 CarouselItem组件 完善组件 完成小圆点 正文 需求是做一个无缝轮播图,我说这不是有很多现成的轮子吗?后来了解到他有一个特殊的需求,他要求小圆点需要在轮播图外面,因为现在大部分插件都是将小圆点写在轮播图内部的,这对于不了解插件内部结构的小伙伴确实不知道如何修改. 很久没有写插件的我准备写一个插件(react) 无缝轮播 无缝轮播从最后一张到第一张的过程中不会原路返回,它就像轮子似的,从结束到开始是无缝连接的,非常

  • React元素与组件的区别示例详解

    目录 从问题出发 元素与组件 元素 组件 问题如何解决 自定义内容 第一种实现方式 第二种实现方式 第三种实现方式 从问题出发 我被问过这样一个问题: 想要实现一个 useTitle 方法,具体使用示例如下: function Header() { const [Title, changeTitle] = useTitle(); return ( <div onClick={() => changeTitle('new title')}> <Title /> </div

  • AngularJS对动态增加的DOM实现ng-keyup事件示例

    我们经常在网页中看到这种形式的内容,如图: 用鼠标点击一下,就变成了一个input,如图: 如果未输入内容,并且鼠标离开后,则变回了原来的样子:如果输入了内容,即使鼠标离开,也保持内容不变,此时输入回车,则添加内容,并清空输入框. 我在想这个是这么实现的?想了一下有这么一个思路:普通情况下这个是一个div或p元素,点击之后变成一个input元素,鼠标离开则变回原元素.代码(含详细注释版)如下: window.onload = function () { // 页面加载完给id为click-to-

随机推荐