单页应用程序 (SPA) 彻底改变了 Web 开发。与传统的多页应用程序相比,它们提供了更加动态和流畅的用户体验。
传统的 Web 应用程序在每次点击时都需要重新加载整个页面,而 SPA 则仅需加载一次 HTML 页面,并在与用户的互动时动态更新页面内容。这种动态交互模式能够达到与桌面应用相同的流畅体验,显著提升了应用的响应速度和交互体验。
为了跟上我们将在本文中讨论的内容,你需要具备一定的 React 基础知识,并了解如何搭建 React 项目。如果你已经具备了这些前提条件,那么请继续阅读本文内容。
React Router DOM 简介
react-router是一个用于 React 应用的路由库,提供了路由管理的基本功能和组件。它不包含与 DOM 相关的特定实现,因此它可以在 React Native 等非 DOM 环境中使用。
react-router-dom是react-router的浏览器端实现,它在react-router的基础上添加了一些专门用于 DOM 的组件。
本文重点深入探讨react-router-dom库,阐述其关键概念,并通过示例展示如何在实际开发中应用这些概念。
最终我们将构建一个具有路由导航功能的简单系统,在这个过程中你将学会如何配置路由、如何处理路由匹配以及实现路由导航。
通过本文的学习,你将会对如何使用react-router-dom构建单页应用程序有个全面而深刻的掌握。
安装 React Router DOM
正如之前所述,react-router-dom旨在为 Web 应用程序提供路由功能。因此,要在 React 应用中集成路由功能,我们需要在项目终端执行以下命令来安装react-router-dom包:
npm install react-router-dom
安装成功后,就可以在我们的 React 项目中配置和使用路由功能了。
React Router DOM 中的核心概念
BrowserRouter
BrowserRouter 是用于包含所有路由组件的容器组件,负责管理应用中的所有路由。它使用浏览器的 History API 来监听 URL 的变化,并确保应用的 UI 与浏览器地址栏中的 URL 保持同步。
要使用 BrowserRouter,我们首先需要从react-router-dom中导入它。
import { BrowserRouter } from "react-router-dom";
function App() {
return (
<BrowserRouter>
</BrowserRouter>
);
}
export default App;
BrowserRouter 提供了一个 basename 属性,用于为应用程序中的所有路由设置一个基础路径。如果你想将应用部署在子域中时,这一点很重要。
<BrowserRouter basename="/shop">
</BrowserRouter>
以上代码将 basename 属性设置为/shop后,所有路由路径都将作为/shop的子路径进行解析。
Routes
Routes 组件是 React Router v6 版本中的一个新组件,用于取代之前版本中的 Switch 组件。Routes的主要作用是渲染第一个与当前 URL 匹配的Route。
要使用 Routes,我们首先需要从react-router-dom中导入它,并将其声明在BrowserRouter组件内部。
import { BrowserRouter, routes } from "react-router-dom";
function App() {
return (
<BrowserRouter>
<Routes>
</Routes>
</BrowserRouter>
);
}
export default App;
Route
Route 组件是一个核心组件,用于声明应用中的路由规则。它的主要职责是根据当前浏览器地址栏中的 URL 来匹配并渲染对应的组件。
Route 组件通过其 path 属性来定义一个路由路径。当浏览器的 URL 与 path 属性匹配时,Route 会渲染其 element 属性指定的组件。
应用程序可以根据需要具有任意数量的Route,并且它们都必须声明在Routes组件内。
假设我们有<Home>和<Pricing>两个组件,下面是一个 Route 组件的基本使用示例:
import { BrowserRouter, Routes, Route } from "react-router-dom";
//ALL COMPONENTS IMPORTS COMES HERE
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Home/>}/>
<Route path="pricing" element={<Pricing/>}/>
</Routes>
</BrowserRouter>
);
}
export default App;
Undeclared Routes
为了处理应用程序中不存在的路由,并显示类似于 404 错误页面,为此,我们需要创建一个新组件,并在其中包含“未找到”相关信息。并在路由配置的最后,使用 Route 组件并为其 path 属性设置一个通配符 *,这表示该路由将匹配所有未匹配先前定义路由的路径。
import { BrowserRouter, Routes, Route } from "react-router-dom";
//ALL COMPONENTS IMPORTS COMES HERE
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Home/>}/>
<Route path="pricing" element={<Pricing/>}/>
<Route path="*" element={<PageNotFound/>}/>
</Routes>
</BrowserRouter>
);
}
export default App;
Nested Routes
在某些场景中,路由可能需要包含嵌套的子路由。
import { BrowserRouter, Routes, Route } from "react-router-dom";
//ALL COMPONENTS IMPORTS COMES HERE
function App() {
return (
<BrowserRouter>
<Routes>
<Route path="/" element={<Home/>}/>
<Route path="pricing" element={<Pricing/>}/>
<Route path="categories" element={<Categories/>}>
<Route path="male" element={<Male/>}/>
<Route path="female" element={<Female/>}/>
</Route>
<Route path="*" element={<PageNotFound/>}/>
</Routes>
</BrowserRouter>
);
}
export default App;
当访问嵌套路由时,浏览器地址栏的 URL 将显示为形式如 /categories/male 或 /categories/female 的格式。
Link
Link 组件是一个用于在应用中创建导航链接的核心组件。它允许用户在不重新加载页面的情况下导航到不同的路由。它有一个to属性,用于指定导航的目标位置。
import { Link } from "react-router-dom";
export default function PageNav() {
return (
<>
<Link to="/">Home</Link>
<Link to="pricing">Pricing</Link>
</>
);
}
提示:为了确保PageNav作为导航菜单始终固定显示在页面顶部,我们所创建的PageNav组件应该放在App.jsx文件中,确切位置是在BrowserRouter标签内,且位于Routes组件之前。
import { BrowserRouter, Routes, Route } from "react-router-dom";
//ALL COMPONENTS IMPORTS COMES HERE
function App() {
return (
<BrowserRouter>
<PageNav/>
<Routes>
<Route path="/" element={<Home/>}/>
<Route path="pricing" element={<Pricing/>}/>
<Route path="categories" element={<Categories/>}>
<Route path="male" element={<Male/>}/>
<Route path="female" element={<Female/>}/>
</Route>
<Route path="*" element={<PageNotFound/>}/>
</Routes>
</BrowserRouter>
);
}
export default App;
NavLink
NavLink 组件是 Link 组件的一个特殊版本,专门用于在导航菜单中标记当前活动的路由。
import { NavLink } from "react-router-dom";
export default function PageNav() {
return (
<>
<NavLink to="/">Home</NavLink>
<NavLink to="pricing">Pricing</NavLink>
</>
);
}
Outlet
Outlet是嵌套路由的核心部分,它用于在父路由组件中渲染匹配的子路由组件。
import { NavLink, Outlet } from "react-router-dom";
export default function Categories() {
return (
<>
<NavLink to="men">
Men
</NavLink>
<NavLink to="women">
Women
</NavLink>
<Outlet />
</>
);
}
这允许在嵌套路由中呈现子路由 UI。
useNavigate Hook
useNavigate 是 react-router-dom 提供的一个钩子(Hook),它允许我们在 React 组件中导航到不同的页面。
useNavigate 返回一个函数,我们可以调用这个函数来在应用中导航到不同的路由。这个函数可以接受一个字符串参数,表示要导航到的路径,或者一个对象,包含 to、replace 和 state 等属性。
在应用程序中使用该钩子可以有多种方式。首先,我们需要导入 useNavigate,调用并将其返回值赋值给变量 navigate 。
import { useNavigate } from "react-router-dom";
export default function Homepage() {
const navigate = useNavigate();
return (
<>
<h1>This is the Homepage</h1>
</>
);
}
我们可以在应用程序中通过以下方式使用 navigate:
- 通过
onClick属性为一个按钮赋予导航功能。
<button onClick={() => navigate("/categories")}>Go to Categories</button>
- 将其与
Link组件一起使用。
<Link to={navigate("/categories")}>Go to Categories</Link>
- 在 navigate 中使用数字来指定要导航到的历史堆栈中的位置,而不是使用路径。这个数字表示我们希望向后导航的历史记录数量。
<Link to={navigate(-1)}>Go one step backwards</Link>
useParams Hook
useParams 是 react-router-dom 提供的一个钩子(Hook),它允许我们在组件中访问当前路由的参数。这个钩子特别适用于动态路由,即那些路径中包含参数的路由。
useParams 返回一个对象,该对象包含当前 URL 中所有参数的键值对。
下面的示例展示了一个 OrderPage 组件,该组件根据 URL 中的客户 ID 为每个客户展示其专属页面。当访问的 URL 为 /customer/123 时,:id 参数的值将是 123。
import { useParams } from "react-router-dom";
function App() {
const {id} = useParams()
return (
<BrowserRouter>
<Routes>
<Route path="customer">
<Route path=":id" element={<OrderPage/>}/>
</Route>
</Routes>
</BrowserRouter>
);
}
export default App;
结语
本文深入探讨了在 React Web 应用程序中如何借助 Web 专用路由库 react-router-dom 构建更高效、响应更迅速的单页应用程序(SPA),最终帮助我们为用户提供满意的、交互更流畅的 Web 应用产品提供助力。