React Router初学者入门指南(2023版)

2023-10-27 16:14:39 浏览数 (2)

React Router,简单来说,是一个帮助处理React应用程序中导航和路由的库。它是用于管理React中路由的最流行的路由工具。如果你对路由的概念不熟悉,可以将其视为在网站的不同部分之间导航的过程。例如,当你进入网站的“联系我们”部分时,你已经成功进行了一次路由过程。本文将为您提供有关React Router的所有细节,以便您可以充分利用它。

如果你对React Router还不熟悉,你可能习惯使用普通的链接(a标签)在你的应用程序中进行导航。然而,当你想在导航时保留应用程序的当前状态时,就会出现问题。不幸的是,普通的链接通常会触发页面刷新来显示组件,从而破坏用户体验。这就是React Router的用武之地。

React Router允许您在应用程序中定义不同的路由,并将它们链接到各自的组件,而无需重新加载页面。这种方法使得React Router能够轻松更新页面上的内容,并使网站感觉像一个原生应用程序。

使用React Router还有其他好处,比如创建复杂的导航、无缝的页面导航结构以及对动态URL的支持。

设置环境

要理解React Router的工作原理,最好的方法之一是构建一个简单的网站。因此,让我们构建一个小型的历史网站,不要太复杂。

所以,让我们准备好一切开始使用React Router所需的东西。

安装React:有几种方法可以做到这一点,但让我们选择最简单的方法:create-react-app(CRA)。通过代码编辑器终端安装React,运行以下命令:

代码语言:javascript复制
npx create-react-app history-app

然后,通过运行cd history-app导航到创建的React应用程序。

  • 安装React Router:要在React网站中安装react-router包,请在终端中运行以下命令:
代码语言:javascript复制
npm install react-router-dom

这个命令允许你安装React Router,一个必要的包。

完成后,您可以通过运行npm start来启动React应用程序。就是这样!React和React Router已经准备好使用了。

让我们添加一些React组件,以便在历史应用程序上获得一些虚拟内容。您只需将其复制并粘贴到App.js中,即默认的应用程序组件。

代码语言:javascript复制
export default function App() {
 return (
   <>
     <Home />
   </>
 );
}

function Home() {
 return (
   <div>
     <h1>The Paradise of History</h1>
     <p>
       Lorem ipsum dolor sit amet consectetur adipisicing elit. Nihil vero
       laudantium repella
     </p>
   </div>
 );
}

function Eras() {
 return (
   <div>
     <h1>The Eras of Time</h1>
     <ul>
       <li>
         <a href="/">Medieval</a>
       </li>
       <li>
         <a href="/">Digital</a>
       </li>
     </ul>
   </div>
 );
}

运行后的效果

理解路由概念

在我们继续之前,让我们快速了解一些React Router中的关键概念:

History Stack:React Router智能地使用HTML5 History API来跟踪用户的导航历史。当用户访问一个新的URL时,React Router将该URL推送到历史堆栈中。当用户导航到其他URL时,它们也会被推送到堆栈中。这就是React Router在不刷新页面的情况下来回导航路由的方式。

Location:这指的是在浏览网站时当前所在的URL。它是历史堆栈中的顶级URL,以及React Router如何动态更改显示的内容以匹配正确的URL。

在一些浏览器中,比如Chrome,你可以点击并长按“返回”按钮来查看历史记录中所有的URL列表。

浏览器路由器及其用途

众所周知,React使用组件和钩子,React Router也是如此。而React Router提供的一个关键组件是。

就像body元素是网站的骨干一样,BrowserRouter 对于 React Router 也是如此。它为网站内所有可能的路由提供了基础。

注意:BrowserRouter使用HTML5 History API来操作浏览器的URL,并将其与当前显示的页面保持同步。

BrowserRouter可以放置在应用程序的任何位置,但通常情况下,您会希望将BrowserRouter放置在组件树的顶部,以包裹整个应用程序的组件。

现在,回到构建我们简单的历史网站的过程中。为了实现BrowserRouter,将整个App组件包裹在其中。要做到这一点,请转到index.js文件:

代码语言:javascript复制
import { BrowserRouter } from "react-router-dom";

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
 <React.StrictMode>
   <BrowserRouter>
     <App />
   </BrowserRouter>
 </React.StrictMode>
);

通过 <BrowserRouter /> App 组件,路由功能在 App 组件中的所有组件中都可用。

关于BrowserRouter的内容就这些了,我们继续吧。

值得注意的是,还有其他类似的组件可用,比如 MemoryRouter、StaticRouter 等等。

使用 Routes 和 Route

要完全掌握React Router中的 Routes 组件的作用,首先我们需要了解 Route 的作用。

Route

简单来说, Route 定义了一个特定的URL路径,并指向在访问该URL路径时应该渲染的组件。

路由组件有两个主要属性:

Path:此属性接受一个字符串,用于指定 Route 的路径。例如,如果有一个 Route ,其 path 设置为 "/eras" ,每当URL变为 https://historyApp.com/eras 时,将触发此 Route 。

Element:当 path 属性中的路径被访问时,该属性被分配给要渲染的React组件。因此,如果访问 /eras 路径,则 <Eras /> 组件将在页面上呈现。

这里是一个代码示例:

代码语言:javascript复制
<Route path='/eras' element={<Eras />} />

Routes

Routes 是 Route 组件的容器组件。它负责检查当前URL位置,并将其与子 Route 组件中指定的路径进行比较,以找到匹配项。

在 Routes 内,您可以嵌套所有的 Route 组件,然后在浏览网站时, Routes 会获取当前的URL,并将其与每个子路由组件进行匹配,以找到与之对应的最佳组件。

因此,在历史应用程序中设置 Routes 和 Route 的步骤如下:

代码语言:javascript复制
import { Routes, Route } from 'react-router-dom';

export default function App() {
 return (
   <Routes>
     <Route path="/" element={<Home />} />
     <Route path="/eras" element={<Eras />} />
   </Routes>
 );
}

这段代码中:

  • 首先从 react-router-dom 包中导入 Routes 和 Route 组件。
  • 然后,在 App 组件内部, Routes 组件限制了不同的 Route 组件。
  • 第一个路由的路径设置为("/"),当访问时将渲染 Home 组件。这个默认路由将始终在访问根URL时渲染。
  • 该 /eras 路由与 Eras 组件相关联。这意味着每当URL路径与 /eras 匹配时,将显示 <Eras /> 内容。

当您在地址栏中的根URL后添加 /eras 时,React Router使用 Routes 组件来匹配具有路径设置为 /eras 的确切 Route 。一旦找到,将渲染在匹配的 Route 的 element 属性中定义的组件;在这种情况下,是 <Eras /> 组件。

404 页面

404错误是一个HTTP状态码,当请求的资源或页面无法找到时会显示出来。这可能发生在用户输入了一个不存在的URL时。

React Router 包含了一种处理 404 错误的方式,当访问一个未定义的网址时,会渲染一个自定义组件。

要处理React Router中的404错误,请创建一个 route ,将其 path 属性设置为 * ,并将其 element 属性设置为应该呈现的错误组件。

可以这样实施:

首先,让我们创建一个错误404组件

代码语言:javascript复制
function Error404() {
 return (
   <div>
     <h1>404 — Page Not Found</h1>
     <a href="/">Take me back!</a>
   </div>
 );
}

然后创建一个 route 来渲染 <Error404 />.

代码语言:javascript复制
export default function App() {
 return (
   <Routes>
     <Route path="/" element={<Home />} />
     <Route path="/eras" element={<Eras />} />
     {/* 404 page */}
     <Route path="*" element={<Error404 />} />
   </Routes>
 );
}

有了这个设置,每当访问一个不存在的URL时,React Router会自动使用 route 组件,并将 path 设置为 * ,然后渲染其元素,即 Error404 组件。

现在,我们可以放心地确保网站能够处理任何意外的URL。

路由之间的连接

到目前为止,我们只讨论了如何通过手动在地址栏中输入URL来访问路由。然而,这种方式并不理想,因为用户必须记住每个页面的确切URL才能访问。

a 标签通常用于解决这个问题,但它有一些限制。为了绕过这些限制,React Router使用 Link 组件。

在React Router中, Link 是路由导航的主要方式。链接组件在底层使用 a 标签,但通过阻止默认页面重新加载来增强它。相反, Link 将其 to 属性中的URL推送到历史堆栈,然后 routes 组件找到具有相同URL的匹配 route 并显示相关组件。

React Router使用 Link 组件而不是 a 标签,因为 Link 被设计用于防止页面重新加载,保留应用程序状态,并在路由之间提供无缝导航。

这是在历史网站中使用 Link 的方法。前往 App.js 并创建一个导航组件:

代码语言:javascript复制
import { Link } from "react-router-dom";

function Nav() {
 return (
   <ul className='nav'>
     <li>
       <Link to='/'>Home</NavLink>
     </li>
     <li>
       <Link to='/eras'>Eras</NavLink>
     </li>
   </ul>
 );
}

首先从 react-router-dom 导入 Link 组件。然后,创建一个功能组件 Nav ,用作历史网站的导航。

这个 Nav 组件遵循了典型导航菜单的结构;只是使用了 Link 组件而不是 a 标签。

每个 <Link /> 都有一个特定的路径分配给 to 属性;这为 Link 设置了目标路由。因此,当点击任何这些链接时,React Router会从 to 属性获取URL,匹配正确的 route 路径,并渲染指定的组件。

由于 Nav 组件应该在所有页面上可见,让我们将其放置在 App 组件的顶部:

代码语言:javascript复制
export default function App() {
 return (
   <>
     <Nav />
     <Routes>
       <Route path='/' element={<Home />} />
       <Route path='/eras' element={<Eras />} />
       <Route path='*' element={<Error404 />} />
     </Routes>
   </>
 );
}

我们还可以给它添加一些简单的样式来增加吸引力:App.css

代码语言:javascript复制
a {
 text-decoration: none;
 color: inherit;
}
a:hover {
 color: #e32a30;
}

.nav {
 list-style: none;
 display: flex;
 width: 500px;
 justify-content: space-around;
 align-items: center;
 font-size: 1.1rem;
 font-weight: bold;
}

NavLink 与 Link 的不同

React Router有一个叫做 NavLink 的组件。它类似于 Link ,但主要用于处理菜单导航链接,不同于 Link 组件,后者可用于任何类型的链接。

NavLink 和 Link 之间的主要区别是 NavLink 能够检测自身是否处于活动状态。当 NavLink 检测到自身处于活动状态时,默认会给其组件添加一个 active 类。

由于历史网站中存在导航菜单,让我们将 Link 组件更新为 NavLink

代码语言:javascript复制
import { Link, NavLink } from "react-router-dom";

function Nav() {
 return (
   <ul className='nav'>
     <li>
       <NavLink to='/'>Home</NavLink>
     </li>
     <li>
       <NavLink to='/eras'>Eras</NavLink>
     </li>
   </ul>
 );
}

active 类可以使用CSS进行自定义。前往 App.css 进行修改:

代码语言:javascript复制
.active {
 color: #e32a30;
}

总的来说, NavLink 在创建导航菜单链接时比 Link 组件更强大。

嵌套路由

在React Router中,嵌套可以被视为在路由之间建立父子连接。这可以用来组织共享相同URL路径的路由。

嵌套路由使用一个 Route 组件作为父路由,另一个 Route 组件用于定义父路由内的子路由。因此,只有在父路由上时才能渲染子路由。

在历史网站上,可以在时代部分找到“中世纪(Medieval)”和“数字化(Digital)”这两个可用的时代类别。因此,要访问这些时代的详细信息,我们可以将它们嵌套在 /eras 路径中。

让我们将这个功能添加到历史网站上:

创建“Medieval”和“Digital”组件:

代码语言:javascript复制
function MedievalEra() {
 return (
   <div>
     <hr />
     <h3>The Medieval Era</h3>
     <p>Lorem ipsum dolor sit amet.</p>
   </div>
 );
}

function DigitalEra() {
 return (
   <div>
     <hr />
     <h3>The Digital Era</h3>
     <p>Lorem ipsum dolor sit amet.</p>
   </div>
 );
}

转到 App 组件,并在 /eras 路由内创建嵌套路由:

代码语言:javascript复制
export default function App() {
 return (
   <>
     <Nav />
     <Routes>
       <Route path="/" element={<Home />} />
       <Route path="/eras" element={<Eras />}>
         <Route path="medieval" element={<MedievalEra />} />
         <Route path="digital" element={<DigitalEra />} />
       </Route>
       <Route path="*" element={<Error404 />} />
     </Routes>
   </>
 );
}

此时,导航到 /eras/medieval 或 /eras/digital 应该分别呈现 <MedievalEra /> 和 <DigitalEra /> 组件。然而,它不会按预期呈现。

这是因为React Router不知道如何放置这些嵌套组件。为了解决这个问题,React Router提供了一个名为 Outlet 的组件,可以明确指出嵌套路由组件应该放置在哪里。

导入 Outlet 组件:

代码语言:javascript复制
import { Outlet } from "react-router-dom";

将 Outlet 组件放置在 Eras 组件内部:

代码语言:javascript复制
function Eras() {
 return (
   <div>
     <h1>The Eras of Time</h1>
     <ul>
       <li>
         <Link to="medieval">Medieval</Link>
       </li>
       <li>
         <Link to="digital">Digital</Link>
       </li>
     </ul>

     <Outlet />
   </div>
 );
}

在这段代码中,之前使用的 a 标签已被替换为 Link 组件,并将相应的路径放置在 to 属性中。

在此之后, <Outlet /> 组件将被放置在下方,因为这是嵌套路由组件将被渲染的位置。

嵌套路由有各种用途,比如层次化组织路由、代码效率、提高性能等。

动态路由与useParams

动态路由是一个概念,它允许您创建不是硬编码的路由,而是根据用户操作或数据生成的路由。

React Router使用 Route 组件和 useParams 钩子来处理动态路由。

设置动态路由时,在 route 组件的 path 属性中使用占位符(用冒号 : 表示)。

就像这样:

代码语言:javascript复制
<Route path="/eras/:type" element={<EraType />} />

这里,对于 Route 的占位符是 : type ,它表示 type 参数的值将会动态生成。

React Router 提供了一个叫做 useParams 的钩子,用于有效处理动态路由。

基本上, useParams hook 返回一个包含来自 Route 组件的动态值的对象,该值可以在负责渲染动态内容的组件中使用。

让我们看看它是如何工作的:

代码语言:javascript复制
import { useParams } from "react-router-dom";

function EraType() {
 const { type } = useParams();

 return (
   <div>
     <hr />
     <h3>The {type} Era</h3>
   </div>
 );
}

现在更新在 /eras 中找到的路由,以包括动态路由:

代码语言:javascript复制
export default function App() {
 return (
   <>
     <Nav />
     <Routes>
       <Route path='/' element={<Home />} />
       <Route path='/eras' element={<Eras />}>
         <Route path='medieval' element={<MedievalEra />} />
         <Route path='digital' element={<DigitalEra />} />
         {/* Dynamic route */}
         <Route path=':type' element={<EraType />} />
       </Route>
       <Route path='*' element={<Error404 />} />
     </Routes>
   </>
 );
}

有了这个动态 Route ,当你在 /eras 路由内导航时,像 /eras/ancient 这样。值“ancient”是动态路径,并且可以通过从 useParams 提取的 type 变量进行访问。

由于嵌套的路由结构, <Eras /> 组件内的 <EraType /> 被渲染出来。

这只是 useParams 的一个基本用例;这个钩子可以用于其他方式,比如从API中获取类似的动态数据。

使用useRoutes钩子

React Router 提供的另一个钩子是 useRoutes 钩子。

这个钩子只是React Router中用于结构化 Routes 和 Route 的另一种方式。它的工作原理是:不使用React组件(JSX)的形式,而是使用JavaScript对象。

在 App.js 中,这是我们如何构建 Routes 和 Route 组件的结构:

代码语言:javascript复制
export default function App() {
 return (
   <>
     <Nav />
     <Routes>
       <Route path='/' element={<Home />} />
       <Route path='/eras' element={<Eras />}>
         <Route path='medieval' element={<MedievalEra />} />
         <Route path='digital' element={<DigitalEra />} />
         <Route path=':type' element={<EraType />} />
       </Route>
       <Route path='*' element={<Error404 />} />
     </Routes>
   </>
 );
}

现在,通过使用 useRoutes 钩子,代码可以重构如下:

代码语言:javascript复制
import { useRoutes } from 'react-router-dom';

export default function App() {
 const routes = useRoutes([
   {
     path: "/",
     element: <Home />,
   },
   {
     path: "/eras",
     element: <Eras />,
     children: [
       {
         path: "medieval",
         element: <MedievalEra />,
       },
       {
         path: "digital",
         element: <DigitalEra />,
       },
       {
         path: ":type",
         element: <EraType />,
       },
     ],
   },
   {
     path: "*",
     element: <Error404 />,
   },
 ]);

 return (
   <>
     <Nav />
     {routes}
   </>
 );
}

useRoutes 钩子从 react-router-dom 导入。然后,一个路由对象数组被传递给 useRoutes 。每个路由对象都有一个 path 和 element 属性,用于指定路径和在路由匹配时应该渲染的组件。

所以,在 useRoutes 钩子或 Routes 和 Route 组件之间的选择归结为个人偏好。选择最适合你风格的那个。

结束

总之,学习React Router是React开发者应该迈出的重要一步。通过使用这个工具,在应用中管理路由导航和创建良好结构化的路由系统变得轻而易举。

0 人点赞