React 路由快速启动指南(全)
原文:
zh.annas-archive.org/md5/64054E4C94EED50A4AF17DC3BC635620
译者:飞龙
前言
Facebook 的 React 框架重新定义了前端应用程序的构建方式。React Router 已成为使用 React 构建的应用程序的事实标准路由框架。通过其最新的 4 版本发布,该库已经在 React 中重写,并且它允许您以声明方式处理路由。在本书中,您将学习 react-router 库如何在任何 React 应用程序中使用,包括使用 React Native 开发的 Web 和原生移动应用程序。该书还涵盖了诸如服务器端路由和 Redux 与 React Router 集成等主题。
这本书适合谁
本书适用于考虑使用 React 和 React Router 构建应用程序的 Web 和原生移动应用程序开发人员。了解 React 框架和 JavaScript 的一些知识将有助于理解本书中讨论的概念。
要充分利用这本书
React Router 用于使用 React 开发的 Web 和原生应用程序。本书假定您对 JavaScript 有很好的理解,并且了解 ECMAScript 6 中引入的一些新语言特性,例如类和扩展运算符。
本书简要介绍了 React 和基于组件的架构。React 的一些其他核心概念在reactjs.org
有文档记录。
本书假定读者已经使用 Node.js 和 NPM 从 NPM 存储库安装了库和软件包。
下载示例代码文件
您可以从www.packt.com的帐户中下载本书的示例代码文件。如果您在其他地方购买了这本书,您可以访问www.packt.com/support并注册,以便文件直接通过电子邮件发送给您。
您可以按照以下步骤下载代码文件:
-
在www.packt.com上登录或注册
-
选择“支持”选项卡
-
单击“代码下载和勘误”
-
在搜索框中输入书名,然后按照屏幕上的说明操作。
下载文件后,请确保您使用最新版本的解压缩或提取文件夹:
-
WinRAR/Windows 的 7-Zip
-
Mac 的 Zipeg/iZip/UnRarX
-
7-Zip/PeaZip 适用于 Linux
该书的代码包也托管在 GitHub 上,网址为github.com/PacktPublishing/React-Router-Quick-Start-Guide
。如果代码有更新,将在现有的 GitHub 存储库上进行更新。
我们还有其他代码包,来自我们丰富的图书和视频目录,可在github.com/PacktPublishing/
上找到。去看看吧!
下载彩色图片
我们还提供了一个 PDF 文件,其中包含本书中使用的屏幕截图/图表的彩色图片。您可以在这里下载:www.packtpub.com/sites/default/files/downloads/9781789532555_ColorImages.pdf.
使用的约定
本书中使用了许多文本约定。
CodeInText
:指示文本中的代码词、数据库表名、文件夹名、文件名、文件扩展名、路径名、虚拟 URL、用户输入和 Twitter 句柄。这是一个例子:“将下载的WebStorm-10*.dmg
磁盘映像文件挂载为系统中的另一个磁盘。”
代码块设置如下:
In GitHubComponent
GitHub ID - mjackson
当我们希望引起您对代码块的特定部分的注意时,相关行或项目将以粗体显示:
<Route
to='/github/**:githubID**'
component={GitHubComponent} />
任何命令行输入或输出都以以下方式编写:
Root:
path: /category, isExact: true
粗体:表示新术语、重要单词或屏幕上看到的单词。例如,菜单或对话框中的单词会以这种方式出现在文本中。这是一个例子:“从管理面板中选择系统信息。”
警告或重要说明会出现在这样的地方。提示和技巧会出现在这样的地方。
第一章:React Router 4 简介和创建您的第一个路由
单页应用程序(SPA)已成为开发 Web 应用程序的事实标准。许多 JavaScript 库和框架已经出现,帮助前端工程师开发 SPA。其中包括 React、Angular、Ember 和 Backbone 等。这些库或框架抽象了原生 API,并提供了可以用于更快地构建应用程序的服务和组件。SPA 是提供流畅用户体验的绝佳选择;当用户在网站中浏览时,会触发 HTTP 请求,只会更新页面的某些部分,而不是请求整个页面的服务器。
React 是一个开源的 JavaScript 库,帮助您构建 Web 和移动应用程序中的用户界面和视图层。它鼓励开发人员将视图层视为可以在整个应用程序中重用的组件集合。大多数前端框架都包含一个路由包,它使您能够在用户点击网站上提供的各种链接时更新页面的各个部分。前端框架中的路由器会监听 URL 的变化,并通过渲染相应的视图组件来保持应用程序同步。例如,当用户访问'/dashboard'
时,页面将呈现各种仪表板组件,如图表和表格;当用户访问'/user'
时,页面将列出各种用户属性。在基于 React 的应用程序中,需要一个路由器库,因为 React 本身不带有路由器。React-Router 是一个完全基于 React 构建的流行路由库。该库包括各种组件,可用于在用户浏览应用程序时呈现视图。除了匹配 URL 和呈现视图组件外,React-Router 还具有一些功能,可帮助您轻松配置路由。
本章讨论以下主题:
-
React 简介:本节介绍了 React 中的一些核心概念,如基于组件的架构、在 React 中创建组件以及如何向应用程序树中的子组件提供数据
-
React-Router 简介:在这里,我们首先使用
create-react-app
CLI 创建一个 React 应用程序,然后将 React-Router 库('react-router-dom'
包)添加为依赖项 -
创建您的第一个路由:在添加 React-Router 作为依赖项后,使用
<BrowserRouter>
和<Route>
组件创建应用程序的第一个路由。
简要了解 React
React 是一个提供一组组件和服务的 JavaScript 库,使您能够构建用户界面。
以下是来自 reactjs.org
的引用:
"React 是一个声明式、高效、灵活的 JavaScript 库,用于构建用户界面。"
该库由 Facebook 开发和维护,根据 MIT 许可。它被广泛用于构建 Facebook 的各种应用程序,包括 Facebook 网站和 Instagram 网站。
React 使您能够构建视图组件,在应用程序状态更改时进行更新。这里的状态可能指的是底层领域数据,也可能反映用户在应用程序旅程中的位置。React 确保视图组件反映应用程序状态。
React 的一些重要特性:
-
JSX:React 应用程序中的组件使用类似 XML/HTML 的语法,称为 JSX,来渲染视图元素。JSX 允许您在 JavaScript/React 代码中包含 HTML;在 React 组件的渲染函数中使用熟悉的带有属性的 HTML 语法,无需学习新的模板语言。预处理器(如 Babel)将使用 JSX 将 HTML 文本转译为 JavaScript 对象,以便 JavaScript 引擎能够理解。
-
单向数据绑定:React 应用程序组织为一系列嵌套组件;一组不可变值作为属性传递给组件的渲染器,以 HTML 标签的形式。组件不会修改其从父组件接收的属性(或 props);相反,子组件将用户操作传达给其父组件,父组件通过更新组件的状态来修改这些属性。
-
虚拟 DOM:在 React 中,为每个 DOM 对象创建一个相应的虚拟 DOM 对象,其具有与真实 DOM 对象相同的一组属性。但是,虚拟 DOM 对象缺乏在用户与页面交互时更新视图的能力。React 中的组件在检测到状态变化时重新渲染视图元素,这种重新渲染会更新虚拟 DOM 树。然后,React 将此虚拟 DOM 树与更新前创建的快照进行比较,以确定更改的 DOM 对象。最后,React 通过仅更新更改的 DOM 对象来修改真实 DOM。
React 中的基于组件的架构
自 2013 年发布以来,React 已经重新定义了前端应用程序的构建方式。它引入了基于组件的架构的概念,本质上允许您将应用程序视为由小型、自包含的视图组件组成。这些视图组件是可重用的;也就是说,诸如CommentBox
或Footer
之类的组件封装了必要的功能,并可以在站点的各个页面中使用。
在这种情况下,页面本身是一个视图组件,由其他小的视图组件组成,如下所示:
<Dashboard>
<Header>
<Brand />
</Header>
<SideNav>
<NavLink key=”1”>
<NavLink key=”2”>
</SideNav>
<ContentArea>
<Chart>
<Grid data="stockPriceList">
</ContentArea>
<Footer />
</Dashboard>
在这里,<Dashboard>
是一个视图组件,包含了几个其他视图组件(Header
、SideNav
、ContentArea
和Footer
),这些又由小组件(Brand
、NavLink
、Chart
和Grid
)组成。基于组件的架构鼓励您构建提供特定功能并且不与任何父级或同级组件紧密耦合的组件。这些组件实现了某些功能,并提供了一个接口,通过这个接口它们可以被包含在页面中。
在前面的例子中,<Grid>
组件将包括渲染数据的行和列、提供搜索功能,以及按升序或降序对列进行排序的功能。<Grid>
组件将实现所有上述功能,并提供一个接口,通过这个接口它可以被包含在页面中。这里的接口将包括标签名(Grid
)和一组属性(props
),接受来自其父组件的值。在这里,<Grid>
组件可以与后端系统进行接口,并检索数据;然而,这将使组件与给定的后端接口紧密耦合,因此无法重用。理想情况下,视图组件将从其父组件接收数据并相应地进行操作。
<Grid data="stockPriceList" />
在这里,<Grid>
组件通过其data
属性接收包含股票价格信息的列表,并以表格格式呈现这些信息。包含这个<Grid>
组件的组件可以被称为Container
组件,Grid
作为子组件。
Container
组件也是View
组件;然而,它的责任包括为其子组件提供必要的数据来渲染。Container
组件可以发起 HTTP 调用到后端服务并接收渲染其子组件所需的数据。此外,Container
组件还负责将单个视图组件定位在其视图区域内。
创建一个 React 组件
通过扩展 React 提供的Component
类来创建 React 组件如下:
import React, { Component } from 'react';
import './button.css';
export class Button extends Component {
render() {
return (
<button className={this.props.type}>
{this.props.children}
</button>
);
}
}
在这里,Button
类扩展了 React 的Component
类并重写了render
方法。render
方法返回将在页面加载时呈现在 DOM 上的 JSX。type
和children
属性在this.props
中可用。React 允许您通过 props 将数据传递给其组件,并通过以下语法来实现:
import React, { Component } from 'react';
import { Button } from './components/Button/button';
import './App.css';
export default class App extends Component {
render() {
return (
<div className="App">
<Button type="secondary">CANCEL</Button>
<Button type="primary">OK</Button>
</div>
);
}
}
在这里,我们将Button
组件包裹在父组件App
中,以渲染两个按钮元素。type
属性被Button
组件使用来设置CANCEL
和OK
按钮的类名(className
)和Button
标签内提到的文本。这可以通过children
属性来引用。children
属性可以是纯文本或其他视图组件。子组件使用this.props
来引用其父组件提供的数据。'this.props'
中的children
属性提供了父组件在标签之间包含的所有子元素的引用。如果您以前使用过 Angular,请将前面的片段视为类似于在 AngularJS 中使用ng-transclude
或在 Angular 中使用ng-content
来包含元素。
在这里,<App>
组件包含<Button>
组件,可以被称为容器组件,负责在页面上渲染按钮。
下一步是在 DOM 上呈现<App>
组件。<App>
组件充当根组件,即树中的根节点。应用程序中的每个组件都将<App>
组件作为其最顶层的父组件:
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import './index.css';
ReactDOM.render(<App />, document.getElementById('root'));
这段代码包含在index.js
中,它导入了React
和ReactDOM
库。ReactDOM
库有一个render
方法,它接受要渲染的组件作为其第一个参数,并且根组件要渲染到的 DOM 节点的引用作为第二个参数。
运行应用程序时,将呈现在<App>
组件内的内容:
React-Router 简介
React-Router 是用 React 构建的 SPA 的路由库。React-Router 版本 4 是一个完全的重写,并采用了基于组件的架构的 React 哲学。
这是来自 React-Router 文档(reacttraining.com/react-router/
)
“React Router 是一组与您的应用程序声明性地组合的导航组件。无论您是想为您的 Web 应用程序拥有可书签的 URL还是想以React Native中的可组合方式导航,React Router都可以在 React 渲染的任何地方使用--所以随你选择!”
React-Router 可以在 React 可以应用的任何地方使用;也就是说,React-Router 在浏览器和使用 React Native 的本地环境中都可以工作。
该库分为三个包:
-
react-router
:DOM 和本地版本的常见核心组件 -
react-router-dom
:用于浏览器和 Web 应用程序的组件 -
react-router-native
:用于使用 React Native 构建的本地应用程序的组件
该库提供了各种组件,可用于动态添加路由到您的应用程序。React-Router v4 中的动态路由允许您在用户通过应用程序旅程时指定应用程序路由。诸如 AngularJS 和 Express 之类的框架要求您预先指定路由,并且在应用程序引导时需要此路由信息。实际上,React-Router 的早期版本遵循了相同的范例,并且需要提前提供路由配置。
除了在 React 应用程序中进行动态路由和提供流畅导航之外,该库还包括传统网站中可用的各种功能。这些包括以下内容:
-
通过应用程序向后和向前导航,维护历史记录,并恢复应用程序的状态
-
在提供 URL(深度链接)时呈现适当的页面组件
-
将用户从一个路由重定向到另一个路由
-
在没有任何路由匹配 URL 时支持呈现 404 页面
-
支持基于哈希的路由和使用 HTML5 模式的漂亮 URLs
React-Router 是 Facebook 提供的官方路由解决方案是一个常见的误解。实际上,它是一个第三方库,根据 MIT 许可证授权。
使用 React-Router 入门
让我们创建一个 React 应用程序,然后将 React-Router 作为依赖项添加进去。
为了创建一个 React 应用程序,我们将使用create-react-app
CLI。create-react-app
CLI 使创建一个已经工作的应用程序变得更容易。CLI 创建了一个项目脚手架,以便您可以开始使用最新的 JavaScript 功能,并提供了用于为生产环境构建应用程序的脚本。有各种 React 和 React-Router 入门套件可用;然而,使用create-react-app
有助于演示如何将 React-Router 添加到现有的基本 React 应用程序中。
第一步是使用 NPM 全局安装create-react-app
,如下所示:
npm install -g create-react-app
CLI 要求node
版本大于或等于 6,并且npm
版本大于 5.2.0。
安装完 CLI 后,我们将使用create-react-app
命令创建一个新的应用程序,如下所示:
create-react-app react-router-demo-app
当create-react-app
完成安装包时,将显示以下输出:
Inside that directory, you can run several commands:
npm start
Starts the development server.
npm run build
Bundles the app into static files for production.
npm test
Starts the test runner.
npm run eject
Removes this tool and copies build dependencies, configuration
files
and scripts into the app directory. If you do this, you can't
go back!
We suggest that you begin by typing:
cd react-router-demo-app
npm start
如果您使用yarn
包管理器(yarnpkg.com/en/
),则前面片段中的npm
命令将被替换为yarn
。
在安装过程中创建了react-router-demo-app
目录(如果尚不存在)。在该目录内,创建了以下项目结构:
/react-router-demo-app
|--node_modules
|--public
| |--favicon.ico
| |--index.html
| |--manifest.json
|--src
| |--App.css
| |--App.js
| |--App.test.js
| |--index.css
| |--index.js
| |--logo.svg
| |--registerServiceWorker.js
|--package-lock.json
|--package.json
|--README.md
CLI 安装了所有必要的依赖项,如 Babel,用于将 ES6 代码转译为 ES5,从而使您能够利用最新的 JavaScript 功能。它还使用 webpack 创建了一个构建管道配置。安装后,无需额外配置即可启动或构建应用程序。如前面的输出所示,您可以使用npm start
命令启动应用程序,并使用npm build
构建一个生产就绪的应用程序。
运行npm start
后,应用程序将被编译,并将打开一个浏览器窗口,显示“欢迎来到 React”的消息,如下所示:
在index.js
文件中,使用ReactDOM
引用来呈现应用程序的根组件,如下所示:
ReactDOM.render(<App />, document.getElementById('root'));
<App>
组件标记了应用程序启动时将呈现的树的开始。
添加 React-Router 库
现在我们的示例应用程序已经运行起来了,让我们使用npm
添加 React-Router 库作为一个依赖项:
npm install --save react-router-dom
此命令将下载并将react-router-dom
添加到/node_modules
目录中。package.json
文件现在将其包含为一个依赖项:
"dependencies": {
"react": "¹⁶.4.0",
"react-dom": "¹⁶.4.0",
"react-router-dom": "⁴.3.0",
"react-scripts": "1.1.4"
}
在撰写本书时,react-router-dom
的版本为 4.3.0。您可以通过在使用npm
包含库时提到react-router-dom@next
来尝试 alpha 和 beta 版本。
定义应用程序路由
react-router-dom
包括一个<BrowserRouter>
组件,它用作在应用程序中添加路由之前的包装器。要在 React Native 应用程序中使用 React-Router,需要使用react-router-native
包。这将在后面的章节中详细讨论。<BrowserRouter>
组件是路由器接口的一种实现,它利用 HTML5 的历史 API 来使 UI 与 URL 路径保持同步。
第一步是使用<BrowserRouter>
将应用程序的根组件包装起来,如下所示:
import { BrowserRouter } from 'react-router-dom';
ReactDOM.render(
<BrowserRouter>
<App />
</BrowserRouter>,
document.getElementById('root')
);
将您的应用程序包装在<BrowserRouter>
中将为我们的<App>
组件创建一个 history 实例,使其所有子组件都可以访问来自原生浏览器历史 API 的 props。这允许组件匹配 URL 路径并呈现适当的页面组件。
History 是一个 JavaScript 库,它允许您管理历史堆栈导航,并有助于在会话之间保持状态。
在 React-Router 中的路由实际上并不是路由-它是基于与当前 URL 路径匹配的模式的组件的条件渲染。要定义路由,我们需要两个信息:要匹配的 URL 路径和要呈现的组件。让我们创建两个组件,HomeComponent
和DashboardComponent
,分别在/home
和/dashboard
上呈现。
在src/components/home/home.component.js
中:
import React from 'react'; export const HomeComponent = () => ( <div> Inside Home route </div> );
在src/components/dashboard/dashboard.component.js
中:
import React from 'react'; export const DashboardComponent = () => ( <div className="dashboard"> Inside Dashboard route </div> );
由于我们从前面的组件返回 JSX,所以需要import
语句。
下一步是使用Route
组件(来自'react-router-dom'
)定义路由。Route
组件接受几个 props,但在本例中,我们将使用path
和component
。
在App.js
中:
class App extends Component { render() { return ( <div className="container"> <Route path="/home" component={HomeComponent} /> <Route path="/dashboard" component={DashboardComponent} /> </div> ); } } export default App;
在这里,我们在<App>
组件的'render'
方法中定义路由。每个<Route>
组件都有一个path
属性,它提到要匹配的 URL 路径,以及一个component
属性,提到一旦路径匹配 URL 就要呈现的组件。
在前面的示例中,该组件是在不扩展 React 组件类的情况下创建的。如果通过将扩展 React 组件类创建的组件作为component
属性的值提供,则每次<Route>
呈现组件时都会调用组件的生命周期方法componentWillMount
和componentWillUnmount
。
当您运行应用程序(npm start
)并访问localhost:3000/home
时,将呈现HomeComponent
并显示消息“Inside Home Component”。类似地,当您访问localhost:3000/dashboard
时,将呈现DashboardComponent
。
<BrowserRouter>
创建一个History
对象,它用于跟踪当前位置并在位置更改时重新渲染站点。<BrowserRouter>
通过 React 的上下文将History
对象提供给其后代子组件。如果一个Route
组件没有<BrowserRouter>
作为其父级,它将无法工作。
另外,<BrowserRouter>
必须只有一个子元素的要求。在下面的片段中,<BrowserRouter>
给出了两个子元素:
<BrowserRouter>
<Route
path="/home"
component={HomeComponent} />
<Route
path="/dashboard"
component={DashboardComponent} />
</BrowserRouter>
上述代码将导致错误,例如“<Route>
组件包装在另一个元素中,例如div
或React Fragment
。
React fragment
用于将一组子元素分组,而不向 DOM 添加额外的节点。当组件返回多个元素时,使用片段。
除了BrowserRouter
之外,React-Router 库中还有其他类型的路由器:HashRouter
,MemoryRouter
和StaticRouter
。这些将在后面的章节中讨论。
总结
React 是一个用于构建用户界面的 JavaScript 库。与 Angular 和 Ember 等库不同,它们包括路由包,React 库不包括任何帮助进行路由的组件或服务。React-Router 是一个路由库,可以在任何 React 应用程序中使用,包括 Web 或原生应用。React-Router 版本 4 是对早期版本的完全重写,所有组件都是用 React 编写的。该库包括用于 Web 应用程序的react-router-dom
包;用于使用 React-Native 构建的原生应用程序的react-router-native
;以及react-router
,这是react-router-dom
和react-router-native
都依赖的核心包。
create-react-app
CLI 用于快速搭建 React 应用程序。它包括可以用于生成开发和生产环境构建的构建配置脚本。然后将react-router-dom
包添加为应用程序的依赖项。该包包括<BrowserRouter>
组件,它实现了History
接口。应用程序的根组件<App />
被包裹在 React-Router 的<BrowserRouter>
组件中,以使History
对象对应用程序树中的所有组件都可用。
创建我们的第一个路由,包括<Route>
组件。它接受path
和component
作为 props,并在浏览器的 URL 匹配<Route>
路径时渲染组件。
在第二章中,配置路由-在 Route 组件中使用各种选项,详细讨论了<Route>
组件的 props。此外,我们将看看渲染组件接收的各种 props,并考虑如何使用这些 props 来创建嵌套路由。
第二章:配置路由-使用路由组件中的各种选项
React-Router 允许您使用<Route>
组件声明性地定义路由。它是 React-Router 的主要构建块,并在path
prop 中提到的路径值与浏览器的 URL 位置匹配时呈现component
prop 中提到的组件。<Route>
组件像任何其他 React 组件一样,接受一组 props。这些 props 可以更精细地控制浏览器的 URL 路径应该如何匹配<Route>
组件的路径,以及一些其他呈现选项。
在上一章中,我们简要地看到了如何使用<Route>
组件来匹配 URL 路径并呈现组件。在本章中,我们将看一下以下内容:
-
深入研究可以添加到
<Route>
组件的各种 props,例如exact
,strict
,render
,children
和sensitive
。 -
路由组件 props:作为
<Route>
路径匹配的结果呈现的组件接收数据作为 props,然后可以用于创建嵌套路由。 -
路由参数:
<Route>
组件的路径可以配置为从 URL 段接受附加参数,并且可以在呈现的组件中读取这些参数。 -
嵌套或动态路由:可以在呈现的组件中添加
<Route>
组件,而不是在应用程序级别定义路由。因此,呈现的组件为应用程序旅程提供了下一步。 -
从 JSON 配置生成路由:JSON 对象中可用的路由信息可用于向应用程序添加路由。
路由 props
当您查看 React-Router 的源代码时,<Route>
组件接受以下 props:
Route.propTypes = { computedMatch: PropTypes.object, // private, from <Switch> path: PropTypes.string, exact: PropTypes.bool, strict: PropTypes.bool, sensitive: PropTypes.bool, component: PropTypes.func, render: PropTypes.func, children: PropTypes.oneOfType([PropTypes.func, PropTypes.node]), location: PropTypes.object };
让我们在下一节中看看这些 props 的每一个。
exact prop
在我们之前的<Route>
示例中,让我们将'/home'
路由路径更改为'/'
,如下所示:
<div className="container">
<Route
path="/"
component={HomeComponent}
/>
<Route
path="/dashboard"
component={DashboardComponent}
/>
</div>
有了这些路由,当浏览器的 URL 设置为/dashboard
时,您会注意到两个组件的内容如下显示:
Inside Home route
Inside Dashboard route
在这里,'/dashboard'
中的'/'
匹配<Route>
的两个路径'/'
和'/dashboard'
;因此它从两个组件中呈现内容。要使浏览器的location.pathname
与<Route>
组件的路径完全匹配,请向<Route>
添加 exact prop,如下所示:
..
<Route
path="/"
component={HomeComponent}
exact
/>
..
类似地,当您尝试访问'/dashboard'
和'/dashboard/portfolio'
路径时,您会注意到在两种情况下都会呈现DashboardComponent
。为了防止'/dashboard/portfolio'
与具有'/dashboard'
路径的<Route>
组件匹配,添加exact
属性。
React-Router 在内部使用path-to-regexp
库来确定路由元素的路径属性是否与当前位置匹配。
严格属性
当<Route>
路径有尾随斜杠,并且您希望将此路径与浏览器的 URL 匹配,包括尾随斜杠时,请包括strict
属性。例如,在将<Route>
路径从'/dashboard'
更改为'/dashboard/'
后,<Route>
组件仍将匹配不带尾随斜杠的 URL 路径。换句话说,'/dashboard'
将匹配具有'/dashboard/'
路径的<Route>
组件。
但是,在添加strict
属性之后,React-Router 确保<Route>
仅在 URL 有尾随斜杠时匹配:
<Route
path="/dashboard/"
component={DashboardComponent}
strict
/>
有了这个<Route>
配置,'/dashboard'
路径将不匹配。但是,当您在 URL 中添加尾随斜杠时,例如'/dashboard/'
,具有strict
属性的<Route>
组件将匹配,并且将呈现DashboardComponent
。
请注意,如果您提到额外的 URL 段,那么它仍将匹配<Route>
组件中提到的path
属性。例如,如果 URL 路径是'/dashboard/123'
,它将与具有strict
属性的<Route>
组件匹配'/dashboard/'
路径。要匹配包括额外 URL 段的路径,可以在strict
属性旁边指定exact
属性。
敏感属性
<Route>
组件的路径不区分大小写,也就是说,<Route>
组件的路径属性值设置为'/Dashboard'
将匹配'/dashboard'
或'/DASHBOARD'
的 URL 路径。要使<Route>
组件的路径区分大小写,添加sensitive
属性:
<Route
path="/Dashboard" component={DashboardComponent} **sensitive** />
sensitive
属性确保在将其与浏览器的 URL 路径匹配时,考虑路径属性的大小写。通过添加sensitive
属性,可以使用不同的大小写定义具有相同路径名的路由。
<Route
path=**"/Dashboard"** component={DashboardComponent} **sensitive** /> <Route path=**"/dashboard"** component={StockListComponent} **sensitive** />
这段代码将创建两个不同的路由,并且当<Route>
组件的区分大小写路径与浏览器的 URL 路径匹配时,将呈现相应的组件。
使用 render prop 进行内联渲染
我们已经看过component
属性如何在<Route>
路径匹配浏览器的location.pathname
时用于渲染视图。还有两个其他可用于渲染视图的属性:render
和children
。
render
属性用于内联渲染。作为render
属性值的函数应返回一个类似于以下的 React 元素:
<Route
path="/user"
render={() => (
<div> Inside User Route </div>
)}
/>
从前面的代码片段中,当'/user'
路径匹配浏览器的 URL 时,作为render
属性值指定的函数被执行,并且从该函数返回的 React 元素被渲染。
当在同一个<Route>
组件中同时指定component
和render
属性时,component
属性将优先。
使用 children 属性进行内联渲染
children
属性应该在您想要渲染视图的情况下使用,无论是否有路径匹配。children
属性的语法与render
属性类似,如下所示:
<Route
path="/sidenav"
children={() => (
<div> Inside Sidenav route </div>
)}
/>
具有children
属性的<Route>
组件即使未指定path
属性也会被渲染。此外,exact
和strict
属性对具有children
属性的<Route>
组件没有任何影响。
component
和render
属性都优先于children
属性。此外,当component
或render
属性被提及时,只有当路径匹配请求的 URL 时才会渲染视图。
基于路由列表中的位置,具有children
属性的<Route>
组件被渲染。例如,如果前一个<Route>
组件被指定为路由列表中的最后一个条目,则在渲染所有先前匹配的路由之后被渲染。此外,如果前一个<Route>
组件在匹配路由之前列出,则路由的内容在渲染匹配路由的内容之前被渲染,如下所示:
<Route
path="/sidenav"
children={() => ( <div> Inside Sidenav route </div>
)} /> <Route path="/user" render={() => ( <div> Inside User route </div> )} />
在这里,当您尝试访问'/user'
路径时,具有children
属性的<Route>
组件在渲染'/user'
路径之前被渲染。
路由组件属性
当<Route>
路径匹配浏览器的 URL 路径时,被渲染的组件接收特定的props
,例如history
、location
、match
和staticContext
。这些 props 提供的数据包括与路由相关的信息。这些 props 可用于使用<Route>
组件的component
、render
或children
属性渲染的组件。
当您在服务器端渲染应用程序时设置staticContext
属性,并且在客户端路由器中(即使用<BrowserRouter>
接口时)不可用(即设置为undefined
)时。
历史
React-Router 依赖于history
包。history
是一个 JavaScript 库,用于在任何 JavaScript 应用程序中维护会话。请考虑来自history
文档的以下引用(github.com/ReactTraining/history
):
“history是一个 JavaScript 库,让您可以轻松地在 JavaScript 运行的任何地方管理会话历史。history
抽象了各种环境的差异,并提供了一个最小的 API,让您可以管理历史堆栈、导航、确认导航和在会话之间保持状态。”
history
对象有几个属性和方法:
-
动作:当前动作,
PUSH
、POP
或REPLACE
-
长度:历史堆栈中条目的计数
-
位置:包括
hash
、pathname
、search
和state
属性的当前位置 -
hash
:哈希片段 -
pathname
:URL 路径 -
search
:URL 查询字符串 -
状态:使用
location.pushState
从一个路由导航到另一个路由时提供的状态信息 -
block()
: 注册一个提示消息的函数,当用户尝试离开当前页面时将显示该消息。 -
createHref()
: 构造 URL 段的函数;它接受一个带有pathname
、search
和hash
属性的对象。 -
go(n)
: 导航历史堆栈。history.go(-1)
将指针向后移动一个位置,history.go(1)
将指针向前移动一个位置。 -
goBack()
: 将指针向后移动一个位置在history
堆栈中;与history.go(-1)
相同。 -
goForward()
: 将指针向前移动一个位置在history
堆栈中;与history.go(1)
相同。 -
listen(listenerFn)
: 注册一个监听器函数,每当history.location
发生变化时就会调用该函数。 -
push(path, state?)
: 导航到给定的路径名,向history
堆栈添加一个条目。它可以选择接受一个state
参数,用于传递应用程序状态数据。 -
replace(path, state?)
: 一个函数,用于导航到给定的路径名,替换history
堆栈中的当前条目。它还接受一个可选的state
参数。
history
对象由 React-Router 在内部使用,用于在用户尝试在页面之间导航时更新历史堆栈中的条目。它作为 prop 提供给渲染的组件,以便用户可以使用history
对象中的上述方法导航到不同的页面。在下一章中,我们将看看 React-Router 提供的各种 API,帮助您导航到应用程序中定义的不同路由。
位置对象
location
对象提供了表示应用程序当前状态的数据快照。它包括以下属性:pathname
、hash
、search
和state
。导航组件可以为这些 prop 提供值,然后由匹配浏览器 URL 的渲染组件读取。如前所述,我们将在第三章中看看各种导航组件,使用 Link 和 NavLink 组件导航到路由。
位置信息也可以在history
对象中找到;但是,history
对象是可变的,因此应避免在history
对象中访问位置。
匹配对象
match
对象包含有关<Route>
路径如何匹配当前 URL 的信息。它包括url
、path
、isExact
和params
属性。
让我们参考之前使用render
prop 的路由之一:
<Route
path="/user" render={({ match }) => { console.log(match);
return ( <div> Inside User route </div> ); }} />
当您尝试访问/user
路径时,match
对象的属性将具有以下值:
url - '/user'
path - '/user'
params - {}
isExact - true
-
url
: 返回 URL 的匹配部分的字符串 -
path
: 返回路由路径字符串的字符串,即在<Route>
组件的路径 prop 中提到的路径模式 -
params
: 包含传递给路由的路径参数列表的对象(在接下来的部分中将更多地介绍参数) -
isExact
: 一个布尔值;如果 URL 完全匹配提供的path
prop,则为true
如果 URL 段的部分仅匹配<Route>
组件的路径,则isExact
属性为false
。例如,具有/user
路径的<Route>
组件与/user/123
的 URL 不完全匹配,在这种情况下,isExact
为 false。
如前所述,带有 children
属性的 <Route>
组件会被渲染,无论 path
属性是否匹配浏览器的 URL 路径。在这种情况下,如果路径不匹配 URL 段,match
对象将被设置为 null:
<Route
path="/sidenav" children={({ match }) => { console.log(match) return ( <div> Inside Sidenav route </div> ); }} />
使用这个 <Route>
配置时,当您尝试访问 /user
路径时,将匹配带有 /sidenav
路径的 <Route>
组件,因为它有一个 children
属性。然而,在这里,match
对象被设置为 null。这有助于确定带有 children
属性的 <Route>
组件的路径是否匹配了 URL 段。
路由参数
在 React-Router 中,可以配置 <Route>
组件来接受给定对象的 URL 参数。例如,要显示给定 userID
的用户信息,URL 路径可能看起来像 '/user/1'
(userID
为 '1'
的用户)和 '/user/123'
(userID
为 '123'
的用户)。URL 的最后部分是动态的;然而,在每种情况下,渲染的组件都会对给定的 userID
执行相同的操作。
这样的用例示例是 Twitter 的个人资料页面。该页面接受 twitterID
并显示给定用户的动态。
在 to
属性中附加一个以冒号 (