如何使用ReactRouter处理React应用程序中的路由
作为 Write for DOnations 计划的一部分,作者选择了 Creative Commons 来接受捐赠。
介绍
在 React 中,routers 帮助创建并在构成 Web 应用程序的不同 URL 之间导航。 它们允许您的用户在您的应用程序的 组件 之间移动,同时保留用户 状态 ,并且可以为这些组件提供唯一的 URL 以使它们更易于共享。 使用路由器,您可以通过简化站点导航来改善应用的用户体验。
React Router 是最流行的 React 路由框架之一。 该库设计有直观的组件,可让您为您的应用程序构建声明性路由系统。 这意味着您可以准确声明哪些组件具有特定路由。 使用声明式路由,您可以创建人类可读的直观路由,从而更轻松地管理您的应用程序架构。
在本教程中,您将安装和配置 React Router,构建一组路由,并使用 <Link>
组件连接到它们。 您还将构建动态路由,这些路由从您可以在组件中访问的 URL 收集数据。 最后,您将使用 Hooks 访问数据和其他路由信息,并创建嵌套路由,这些路由位于由父路由呈现的组件内。
在本教程结束时,您将能够向任何 React 项目添加路由并从您的路由中读取信息,以便您可以创建响应 URL 数据的灵活组件。
先决条件
- 您将需要一个运行 Node.js 的开发环境; 本教程在 Node.js 版本 10.22.0 和 npm 版本 6.14.6 上进行了测试。 要在 macOS 或 Ubuntu 18.04 上安装它,请按照 如何在 macOS 上安装 Node.js 和创建本地开发环境中的步骤或 的 使用 PPA 部分安装如何在 Ubuntu 18.04 上安装 Node.js。
- 使用 Create React App 设置的 React 开发环境,删除了非必要的样板。 要进行此设置,请按照 步骤 1 — 创建一个空项目的如何管理 React 类组件上的状态教程 。 本教程将使用
router-tutorial
作为项目名称。 - 您将在整个教程中使用 React 组件和自定义 Hook。 您可以在 How To Create Custom Components in React 中了解组件,在 How To Manage State with Hooks on React Components 中了解组件。
- 您还需要 JavaScript、HTML 和 CSS 的基本知识,您可以在我们的 如何使用 HTML 构建网站系列、如何使用 CSS 构建网站系列 中找到这些知识, 以及 如何在 JavaScript 中编码 。
第 1 步 — 安装 React 路由器
在这一步中,你将把 React Router 安装到你的基础项目中。 在这个项目中,您将创建一个关于海洋哺乳动物的小型网站。 每个哺乳动物都需要一个单独的组件,您将使用路由器进行渲染。 安装库后,您将为每种哺乳动物创建一系列组件。 到此步骤结束时,您将为根据路线渲染不同的哺乳动物奠定基础。
首先,安装 React Router 包。 有两个不同的版本:Web 版本和用于 React Native 的原生版本。 您将安装网络版本。
在您的终端中,使用 npm 安装软件包:
npm install react-router-dom
该软件包将安装,安装完成后您将收到一条消息,例如此消息。 您的信息可能略有不同:
Output... + react-router-dom@5.2.0 added 11 packages from 6 contributors and audited 1981 packages in 24.897s 114 packages are looking for funding run `npm fund` for details found 0 vulnerabilities
您现在已经安装了软件包。 在此步骤的剩余部分中,您将创建一系列组件,每个组件都有一个独特的路线。
首先,为三种不同的哺乳动物创建一个目录:海牛、独角鲸和鲸鱼。 运行以下命令:
mkdir src/components/Manatee mkdir src/components/Narwhal mkdir src/components/Whale
接下来,为每只动物创建一个组件。 为每个哺乳动物添加一个 <h2>
标签。 在一个完整的应用程序中,子组件可以像您想要的那样复杂。 他们甚至可以导入和渲染自己的子组件。 对于本教程,您将仅渲染 <h2>
标记。
从海牛组件开始。 在文本编辑器中打开 Manatee.js
:
nano src/components/Manatee/Manatee.js
然后添加基本组件:
路由器教程/src/components/Manatee/Manatee.js
import React from 'react'; export default function Manatee() { return <h2>Manatee</h2>; }
保存并关闭文件。
接下来,为独角鲸创建一个组件:
nano src/components/Narwhal/Narwhal.js
添加相同的基本组件,将 <h2>
更改为 Narwhal
:
路由器教程/src/components/Narwhal/Narwhal.js
import React from 'react'; export default function Narwhal() { return <h2>Narwhal</h2>; }
保存并关闭文件。
最后,为 Whale
创建一个文件:
nano src/components/Whale/Whale.js
添加相同的基本组件,将 <h2>
更改为 Whale
:
路由器教程/src/components/Whale/Whale.js
import React from 'react'; export default function Whale() { return <h2>Whale</h2>; }
保存并关闭文件。 在下一步中,您将开始连接路线; 现在,在您的应用程序中渲染基本组件。
打开App.js
:
nano src/components/App/App.js
在 className
为 wrapper
的 <div>
中添加带有网站名称 (Marine Mammals
) 的 <h1>
标记。 这将用作模板。 包装器和 <h1>
标记将呈现在每个页面上。 在完整的应用程序中,您可能会在每个页面上添加您想要的导航栏或标题组件。
将以下突出显示的行添加到文件中:
路由器教程/src/components/App/App.js
import React from 'react'; import './App.css'; function App() { return ( <div className="wrapper"> <h1>Marine Mammals</h1> </div> ); } export default App;
接下来,导入 Manatee
并在 <div>
内渲染。 这将用作占位符,直到您添加更多路线:
路由器教程/src/components/App/App.js
import React from 'react'; import './App.css'; import Manatee from '../Manatee/Manatee'; function App() { return ( <div className="wrapper"> <h1>Marine Mammals</h1> <Manatee /> </div> ); } export default App;
保存并关闭文件。
现在您已经拥有了所有组件,添加一些填充以给应用程序一点空间。
打开App.css
:
nano src/components/App/App.css
然后将内容替换为以下代码,将 20px
的 padding
添加到 .wrapper
类:
路由器教程/src/components/App/App.css
.wrapper { padding: 20px; }
保存并关闭文件。 当您这样做时,浏览器将刷新以显示您的基本组件:
现在您有一个基本的根组件,您将使用它来显示其他组件。 如果您没有路由器,您可以使用 useState Hook 有条件地显示组件。 但这不会为您的用户提供出色的体验。 每当用户刷新页面时,用户的选择就会消失。 此外,他们将无法为应用程序的特定状态添加书签或共享。 路由器将解决所有这些问题。 路由器将保留用户状态,并为用户提供一个清晰的 URL,他们可以保存或发送给其他人。
在这一步中,您安装了 React Router 并创建了基本组件。 这些组件将是您将按路线显示的各个页面。 在下一步中,您将添加路由并使用 <Link>
组件创建高性能超链接。
第 2 步 - 添加路由
在此步骤中,您将为每个页面创建一个带有单独路由的基本路由器。 您将订购路线以确保正确呈现组件,并且您将使用 <Link>
组件将超链接添加到不会触发页面刷新的项目中。
在这一步结束时,您将拥有一个带有导航的应用程序,该导航将按路线显示您的组件。
React Router 是一个声明式路由框架。 这意味着您将使用标准 React 组件配置路由。 这种方法有几个优点。 首先,它遵循 React 代码的标准声明性。 您不需要在 componentDidMount
方法或 useEffect
Hook 中添加大量代码; 您的路线是组件。 其次,您可以直观地将路由放置在组件内部,而其他组件用作模板。 当您阅读代码时,您会发现动态组件相对于全局视图(如导航或页脚)的确切位置。
要开始添加路线,请打开 App.js
:
nano src/components/App/App.js
<h1>
标签将用作全局页面标题。 由于您希望它出现在每个页面上,因此在标记之后配置路由器。
从 react-router-dom
导入 BrowserRouter
、Route
和 Switch
。 BrowserRouter
将是基本配置。 Switch
将包装动态路由,而 Route
组件将配置特定路由并包装应渲染的组件:
路由器教程/src/components/App/App.js
import React from 'react'; import { BrowserRouter, Route, Switch } from 'react-router-dom'; import './App.css'; import Manatee from '../Manatee/Manatee'; function App() { return ( <div className="wrapper"> <h1>Marine Mammals</h1> <Manatee /> </div> ); } export default App;
添加 BrowserRouter
组件以创建基础路由器。 此组件之外的任何内容都将呈现在每个页面上,因此请将其放在 <h1>
标记之后。 此外,如果您有想要使用的站点范围的 context 或其他一些存储,例如 Redux,请将这些组件放在路由器之外。 这将使它们可用于任何路线上的所有组件:
路由器教程/src/components/App/App.js
import React from 'react'; import { BrowserRouter, Route, Switch } from 'react-router-dom'; import './App.css'; import Manatee from '../Manatee/Manatee'; function App() { return ( <div className="wrapper"> <h1>Marine Mammals</h1> <BrowserRouter> <Manatee /> </BrowserRouter> </div> ); } export default App;
接下来,在 BrowserRouter
中添加 Switch
组件。 这个组件将激活正确的路由,很像 JavaScript switch 语句。 在 Switch
内部,为每条路线添加一个 Route
组件。 在这种情况下,您需要以下路线:/manataee
、/narwhal
和 /whale
。 Route
组件将 path
作为参数并围绕子组件。 当路由处于活动状态时,子组件将显示。
为路径 /
创建路由并渲染 Manatee
组件:
路由器教程/src/components/App/App.js
import React from 'react'; import { BrowserRouter, Route, Switch } from 'react-router-dom'; import './App.css'; import Manatee from '../Manatee/Manatee'; function App() { return ( <div className="wrapper"> <h1>Marine Mammals</h1> <BrowserRouter> <Switch> <Route path="/"> <Manatee /> </Route> </Switch> </BrowserRouter> </div> ); } export default App;
保存文件。 当您这样做时,浏览器将重新加载,您将找到海牛组件的信息:
如果您尝试不同的路线,例如 http://localhost:3000/whale,您仍然会找到海牛组件。
Switch
组件将呈现与该模式匹配的第一个路由。 任何路由都将匹配 /
,因此它会在每个页面上呈现。 这也意味着顺序很重要。 由于路由器会在找到匹配项后立即退出,因此始终将更具体的路由放在不太具体的路由之前。 换句话说,/whale
会在 /
之前,而 /whale/beluga
会在 /whale
之前。
如果您希望路由仅匹配写入的路由而不匹配任何子路由,则可以添加 exact
属性。 例如,<Route exact path="/manatee">
将匹配 /manatee
,但不匹配 /manatee/african
。
将 Manatee
组件的路由更新为 /manatee
,然后导入其余组件并为每个组件创建一个路由:
路由器教程/src/components/App/App.js
import React from 'react'; import { BrowserRouter, Route, Switch } from 'react-router-dom'; import './App.css'; import Manatee from '../Manatee/Manatee'; import Narwhal from '../Narwhal/Narwhal'; import Whale from '../Whale/Whale'; function App() { return ( <div className="wrapper"> <h1>Marine Mammals</h1> <BrowserRouter> <Switch> <Route path="/manatee"> <Manatee /> </Route> <Route path="/narwhal"> <Narwhal /> </Route> <Route path="/whale"> <Whale /> </Route> </Switch> </BrowserRouter> </div> ); } export default App;
保存文件。 当你这样做时,浏览器将刷新。 如果你访问 http://localhost:3000/,只会渲染 <h1>
标签,因为没有路由匹配任何 Route
组件:
如果你访问 http://localhost:3000/whale,你会发现 Whale
组件:
现在您有了一些组件,为用户创建导航以在页面之间移动。
使用 <nav>
元素表示您正在创建页面的导航部分。 然后为每个哺乳动物添加一个带有列表项 (<li>
) 和超链接 (<a>
) 的无序列表 (<ul>
):
路由器教程/src/components/App/App.js
import React from 'react'; import { BrowserRouter, Route, Switch } from 'react-router-dom'; import './App.css'; import Manatee from '../Manatee/Manatee'; import Narwhal from '../Narwhal/Narwhal'; import Whale from '../Whale/Whale'; function App() { return ( <div className="wrapper"> <h1>Marine Mammals</h1> <nav> <ul> <li><a href="/manatee">Manatee</a></li> <li><a href="/narwhal">Narwhal</a></li> <li><a href="/whale">Whale</a></li> </ul> </nav> <BrowserRouter> ... </BrowserRouter> </div> ); } export default App;
保存文件。 当你这样做时,浏览器会刷新,但会出现问题。 由于您使用的是本机浏览器链接 - <a>
标签 - 您将在任何时候单击链接时获得默认浏览器行为。 这意味着任何时候你点击一个链接,你都会触发一个完整的页面刷新。
请注意,当您单击链接时,网络将重新加载所有 JavaScript 文件。 这对您的用户来说是一个很大的性能成本。
此时,您可以在每个链接上添加一个 click
事件处理程序 并阻止默认操作。 那将是很多工作。 相反,React Router 有一个名为 Link
的特殊组件,它将为您处理工作。 它将创建一个链接标签,但在推送新位置时会阻止默认浏览器行为。
在 App.js
中,从 react-router-dom
导入 Link
。 然后将每个 <a>
替换为 Link
。 您还需要将 href
属性更改为 to
属性。
最后,将 <nav>
组件移动到 BrowserRouter
内部。 这确保 Link
组件由 react-router
控制:
路由器教程/src/components/App/App.js
import React from 'react'; import { BrowserRouter, Link, Route, Switch } from 'react-router-dom'; import './App.css'; import Manatee from '../Manatee/Manatee'; import Narwhal from '../Narwhal/Narwhal'; import Whale from '../Whale/Whale'; function App() { return ( <div className="wrapper"> <h1>Marine Mammals</h1> <BrowserRouter> <nav> <ul> <li><Link to="/manatee">Manatee</Link></li> <li><Link to="/narwhal">Narwhal</Link></li> <li><Link to="/whale">Whale</Link></li> </ul> </nav> <Switch> <Route path="/manatee"> <Manatee /> </Route> <Route path="/narwhal"> <Narwhal /> </Route> <Route path="/whale"> <Whale /> </Route> </Switch> </BrowserRouter> </div> ); } export default App;
保存文件。 当你这样做时,浏览器将刷新。 单击链接时,页面不会刷新,浏览器也不会重新加载 JavaScript 代码:
在这一步中,您将 React Router 添加到当前项目中。 您为每个组件创建了一个路由,并使用 Link
组件添加了一个导航,以便在不刷新页面的情况下在路由之间切换。
在下一步中,您将添加更复杂的路由,这些路由使用 URL 参数呈现不同的组件。
第 3 步 - 使用 Hooks 访问路由数据
在此步骤中,您将使用 URL 查询和参数来创建动态路由。 您将学习如何使用 useLocation
挂钩从搜索参数中提取信息,以及如何使用 useParams
挂钩从动态 URL 中读取信息。
在这一步结束时,您将了解如何访问组件内部的路由信息以及如何使用该信息来动态加载组件。
假设您想向海洋哺乳动物应用程序添加另一个级别。 鲸鱼的种类很多,您可以显示每种鲸鱼的信息。 您有两种选择如何完成此操作:您可以使用当前路线并添加带有搜索参数的特定鲸鱼类型,例如 ?type=beluga
。 您还可以创建一个在基本 URL 后包含特定名称的新路由,例如 /whale/beluga
。 本教程将从搜索参数开始,因为它们很灵活并且可以处理多个不同的查询。
首先,为不同的鲸鱼种类制造新的组件。
在文本编辑器中打开一个新文件 Beluga.js
:
nano src/components/Whale/Beluga.js
添加名称为 Beluga
的 <h3>
标记:
路由器教程/src/components/Whale/Beluga.js
import React from 'react'; export default function Beluga() { return( <h3>Beluga</h3> ); }
对蓝鲸做同样的事情。 在文本编辑器中打开一个新文件 Blue.js
:
nano src/components/Whale/Blue.js
添加名称为 Blue
的 <h3>
标记:
路由器教程/src/components/Whale/Blue.js
import React from 'react'; export default function Blue() { return( <h3>Blue</h3> ); }
保存并关闭文件。
使用搜索参数传递附加信息
接下来,您要将鲸鱼信息作为 搜索参数 传递。 这将使您无需创建新 URL 即可传递信息。
打开 App.js
以便添加新链接:
nano src/components/App/App.js
添加两个新链接,一个指向 /whale?type=beluga
,一个指向 /whale?type=blue
:
路由器教程/src/components/App/App.js
import React from 'react'; import { BrowserRouter, Link, Route, Switch } from 'react-router-dom'; import './App.css'; import Manatee from '../Manatee/Manatee'; import Narwhal from '../Narwhal/Narwhal'; import Whale from '../Whale/Whale'; function App() { return ( <div className="wrapper"> <h1>Marine Mammals</h1> <BrowserRouter> <nav> <ul> <li><Link to="/manatee">Manatee</Link></li> <li><Link to="/narwhal">Narwhal</Link></li> <li><Link to="/whale">Whale</Link></li> <li><Link to="/whale?type=beluga">Beluga Whale</Link></li> <li><Link to="/whale?type=blue">Blue Whale</Link></li> </ul> </nav> <Switch> ... </Switch> </BrowserRouter> </div> ); } export default App;
保存并关闭文件。
如果您单击链接,您仍然会看到常规的鲸鱼页面。 这表明标准路线仍在正常工作:
由于您正确呈现 Whale
组件,因此您需要更新组件以将搜索查询从 URL 中拉出并使用它来呈现正确的子组件。
打开Whale.js
:
nano src/components/Whale/Whale.js
首先,导入 Beluga
和 Blue
组件。 接下来,从 react-router-dom
导入一个名为 useLocation
的 Hook:
路由器教程/src/components/Whale/Whale.js
import React from 'react'; import { useLocation } from 'react-router-dom'; import Beluga from './Beluga'; import Blue from './Blue'; export default function Whale() { return <h2>Whale</h2>; }
useLocation
Hook 从您的页面中提取位置信息。 这不是 React Router 独有的。 location
对象是 所有浏览器 上的标准对象。 如果您打开浏览器控制台并输入 window.location
,您将获得一个包含有关您的 URL 信息的对象。
请注意,位置信息包括 search
,但也包括其他信息,例如 pathname
和完整的 href
。 useLocation
Hook 将为您提供此信息。 在 Whale.js
内部,调用 useLocation
Hook。 Destructure 拉出 search
字段的结果。 这将是一个参数字符串,例如 ?type=beluga
:
路由器教程/src/components/Whale/Whale.js
import React from 'react'; import { useLocation } from 'react-router-dom'; import Beluga from './Beluga'; import Blue from './Blue'; export default function Whale() { const { search } = useLocation(); return <h2>Whale</h2>; }
有许多库,例如 query-string,可以为您解析搜索并将其转换为更易于阅读和更新的 object。 在此示例中,您可以使用正则表达式提取有关鲸鱼 type
的信息。
使用搜索字符串上的.match
方法拉出type
:search.match(/type=(.*)/)
。 正则表达式中的括号会将匹配捕获到结果 array 中。 数组中的第一项是完全匹配:type=beluga
。 第二项是括号中的信息:beluga
。
使用 .match
方法中的数据来渲染正确的子组件:
路由器教程/src/components/Whale/Whale.js
import React from 'react'; import { useLocation } from 'react-router-dom'; import Beluga from './Beluga'; import Blue from './Blue'; export default function Whale() { const { search } = useLocation(); const match = search.match(/type=(.*)/); const type = match?.[1]; return ( <> <h2>Whale</h2> {type === 'beluga' && <Beluga />} {type === 'blue' && <Blue />} </> ); }
符号 ?.
称为 可选链 。 如果值存在,则返回该值。 否则,它将返回 undefined
。 这将在搜索参数为空的情况下保护您的组件。
保存文件。 当你这样做时,浏览器将刷新并呈现不同的鲸鱼:
访问 URL 参数
搜索参数有效,但在这种情况下它们不是最佳解决方案。 通常,您会使用搜索参数来优化页面:切换信息或加载特定数据。 在这种情况下,您不是在优化页面;而是在优化页面。 您正在创建一个新的静态页面。 幸运的是,React Router 提供了一种创建动态 URL 的方法,该方法可以保存称为 URL 参数的可变数据。
打开App.js
:
nano src/components/App/App.js
您无需将鲸鱼信息作为搜索传递,而是将其直接添加到 URL 本身。 这意味着您将 seach 移动到 URL 中,而不是在 ?
之后添加它。 例如,查询 /whale?type=blue
现在将是 /whale/blue
:
路由器教程/src/components/App/App.js
import React from 'react'; import { BrowserRouter, Link, Route, Switch } from 'react-router-dom'; import './App.css'; import Manatee from '../Manatee/Manatee'; import Narwhal from '../Narwhal/Narwhal'; import Whale from '../Whale/Whale'; function App() { return ( <div className="wrapper"> <h1>Marine Mammals</h1> <BrowserRouter> <nav> <ul> <li><Link to="/manatee">Manatee</Link></li> <li><Link to="/narwhal">Narwhal</Link></li> <li><Link to="/whale">Whale</Link></li> <li><Link to="/whale/beluga">Beluga Whale</Link></li> <li><Link to="/whale/blue">Blue Whale</Link></li> </ul> </nav> <Switch> <Route path="/manatee"> <Manatee /> </Route> <Route path="/narwhal"> <Narwhal /> </Route> <Route path="/whale"> <Whale /> </Route> </Switch> </BrowserRouter> </div> ); } export default App;
现在您需要创建一个可以同时捕获 /whale/beluga
和 /whale/blue
的新路由。 您可以手动添加它们,但这不适用于您事先不知道所有可能性的情况,例如当您拥有用户列表或其他动态数据时。
无需为每个路由创建路由,而是将 URL 参数添加到当前路径。 URL 参数是以冒号开头的关键字。 React Router 将使用参数作为通配符,并匹配任何包含该模式的路由。
在这种情况下,创建一个关键字 :type
。 完整的 path
将是 /whale/:type
。 这将匹配以 /whale
开头的任何路由,并将变量信息保存在名为 type
的参数变量中。 此路由将不匹配 /whale
,因为它不包含附加参数。
您可以在新路由之后添加 /whale
作为路由,也可以使用 exact
关键字将其添加到 /whale/:type
的路由之前。
添加 /whale/:type
的新路由,并在当前路由中添加 exact
属性:
路由器教程/src/components/App/App.js
import React from 'react'; import { BrowserRouter, Link, Route, Switch } from 'react-router-dom'; import './App.css'; import Manatee from '../Manatee/Manatee'; import Narwhal from '../Narwhal/Narwhal'; import Whale from '../Whale/Whale'; function App() { return ( <div className="wrapper"> <h1>Marine Mammals</h1> <BrowserRouter> <nav> <ul> <li><Link to="/manatee">Manatee</Link></li> <li><Link to="/narwhal">Narwhal</Link></li> <li><Link to="/whale">Whale</Link></li> <li><Link to="/whale/beluga">Beluga Whale</Link></li> <li><Link to="/whale/blue">Blue Whale</Link></li> </ul> </nav> <Switch> <Route path="/manatee"> <Manatee /> </Route> <Route path="/narwhal"> <Narwhal /> </Route> <Route exact path="/whale"> <Whale /> </Route> <Route path="/whale/:type"> <Whale /> </Route> </Switch> </BrowserRouter> </div> ); } export default App;
保存并关闭文件。 现在您正在传递新信息,您需要访问它并使用这些信息来呈现动态组件。
打开Whale.js
:
nano src/components/Whale/Whale.js
导入 useParams
钩子。 这将连接到您的路由器并将任何 URL 参数提取到一个对象中。 解构对象以提取 type
字段。 去掉解析search
的代码,使用参数有条件地渲染子组件:
路由器教程/src/components/Whale/Whale.js
import React from 'react'; import { useParams } from 'react-router-dom'; import Beluga from './Beluga'; import Blue from './Blue'; export default function Whale() { const { type } = useParams(); return ( <> <h2>Whale</h2> {type === 'beluga' && <Beluga />} {type === 'blue' && <Blue />} </> ); }
保存并关闭文件。 当您这样做时,浏览器将刷新,您将能够使用新的 URL,例如 http://localhost:3000/whale/beluga:
URL 参数是传递条件数据的一种清晰方式。 它们不像搜索参数那样灵活,可以组合或重新排序,但它们更清晰,更容易被搜索引擎索引。
在此步骤中,您使用搜索参数和 URL 参数传递了可变数据。 您还使用了 useLocation
和 useParams
挂钩来提取信息并渲染条件组件。
但是有一个问题:路线列表越来越长,并且您开始使用 /whale
和 /whale/:type
路线接近重复。 React Router 允许您直接在组件中拆分子路由,这意味着您不需要将整个列表放在单个组件中。 在下一步中,您将直接在子组件内渲染路由。
第 4 步 - 嵌套路由
路线可以增长并变得更加复杂。 React Router 使用嵌套路由在子组件内部呈现更具体的路由信息。 在此步骤中,您将使用嵌套路由并在不同组件中添加路由。 在此步骤结束时,您将有不同的选项来呈现您的信息。
在最后一步中,您在 App.js
中添加了路线。 这有一些优点:它将所有路线保存在一个地方,本质上是为您的应用程序创建一个站点地图。 但是它很容易增长并且难以阅读和维护。 嵌套路由将您的路由信息直接分组到将呈现其他组件的组件中,使您能够在整个应用程序中创建迷你模板。
打开App.js
:
nano src/components/App/App.js
移除 /whale/:type
路线并移除 exact
道具,因此您只有一条鲸鱼路线:
路由器教程/src/components/App/App.js
import React from 'react'; import { BrowserRouter, Link, Route, Switch } from 'react-router-dom'; import './App.css'; import Manatee from '../Manatee/Manatee'; import Narwhal from '../Narwhal/Narwhal'; import Whale from '../Whale/Whale'; function App() { return ( <div className="wrapper"> <h1>Marine Mammals</h1> <BrowserRouter> <nav> <ul> <li><Link to="/manatee">Manatee</Link></li> <li><Link to="/narwhal">Narwhal</Link></li> <li><Link to="/whale">Whale</Link></li> <li><Link to="/whale/beluga">Beluga Whale</Link></li> <li><Link to="/whale/blue">Blue Whale</Link></li> </ul> </nav> <Switch> <Route path="/manatee"> <Manatee /> </Route> <Route path="/narwhal"> <Narwhal /> </Route> <Route path="/whale"> <Whale /> </Route> </Switch> </BrowserRouter> </div> ); } export default App;
保存并关闭文件。
接下来,打开 Whale.js
。 这是您将添加嵌套路由的地方。
nano src/components/Whale/Whale.js
你需要做两件事。 首先,使用 useRouteMatch
Hook 获取当前路径。 接下来,渲染新的 <Switch>
和 <Route>
组件以显示正确的组件。
导入 useRouteMatch
。 这将返回一个包含 path
和 url
的对象。 解构对象以获得 path
。 您将以此作为新路线的基础:
路由器教程/src/components/Whale/Whale.js
import React from 'react'; import { useRouteMatch } from 'react-router-dom'; import Beluga from './Beluga'; import Blue from './Blue'; export default function Whale() { const { path } = useRouteMatch(); return ( <> <h2>Whale</h2> {type === 'beluga' && <Beluga />} {type === 'blue' && <Blue />} </> ); }
接下来,导入 Switch
和 Route
以便您可以添加新路线。 您的新路线将与您在 App.js
中创建的路线相同,但您不需要用 BrowserRouter
包装它们。 添加新路由,但在路由前加上 path
。 新组件将准确呈现您放置它们的位置,因此在 <h2>
之后添加新路由:
路由器教程/src/components/Whale/Whale.js
import React from 'react'; import { Switch, Route, useRouteMatch } from 'react-router-dom'; import Beluga from './Beluga'; import Blue from './Blue'; export default function Whale() { const { path } = useRouteMatch(); return ( <> <h2>Whale</h2> <Switch> <Route path={`${path}/beluga`}> <Beluga /> </Route> <Route path={`${path}/blue`}> <Blue /> </Route> </Switch> </> ); }
保存文件。 当您这样做时,浏览器将刷新,您将能够访问子路由。
这是一个额外的代码,但它使子路由与父路由保持一致。 并非所有项目都使用嵌套路由:有些项目更喜欢使用显式列表。 这是团队偏好和一致性的问题。 选择最适合您的项目的选项,您以后可以随时重构。
在此步骤中,您向项目添加了嵌套路由。 您使用 useRouteMatch
Hook 提取了当前路径,并在组件中添加了新路由以在基础组件中呈现新组件。
结论
React Router 是任何 React 项目的重要组成部分。 当您构建单页应用程序时,您将使用路由将您的应用程序分成用户可以轻松且一致地访问的可用部分。
当您开始将组件分成路由时,您将能够利用 代码拆分 、通过查询参数保留状态以及其他工具来改善用户体验。
如果您想阅读更多 React 教程,请查看我们的 React 主题页面 ,或返回 如何在 React.js 系列页面中编码 。