React Router 是 React 生态系统中最受欢迎的第三方库之一,近一半的 React 项目中使用了 React Router,下面就来看看如何在 React 项目中使用 React Router v6 吧!
1. 概述
React Router 创建于 2014 年,是一个用于 React 的声明式、基于组件的客户端和服务端路由库,它可以保持 UI 与 URL 同步,拥有简单的 API 与强大的功能。
大多数现代 React 项目使用 npm、yarn、pnpm 等包管理器来管理项目依赖项。要将 React Router 添加到现有项目,就需要根据使用的包管理器来安装依赖:
// npm npm install react-router-dom@6 // pnpm pnpm add react-router-dom@6 // yarn yarn add react-router-dom@6
接下来,使用 CodeSandBox 来创建一个 React + TypeScript 项目,使用核心库的版本如下:
react
:18.0.0react-dom
:18.0.0react-router
:6.3.0react-router-dom
:6.3.0
Demo 初始目录结构如下:
- public - src - App.tsx - index.tsx - style.css - package.json - tsconfig.json
在介绍 React Router 的概念以前,需要先区分两个概念:
react-router
:为 React 应用提供了路由的核心功能;react-router-dom
:基于 react-router,加入了在浏览器运行环境下的一些功能。
2. 基本使用
(1)BrowserRouter
要想在 React 应用中使用 React Router,就需要在 React 项目的根文件(index.tsx
)中导入 Router 组件:
import { StrictMode } from "react"; import * as ReactDOMClient from "react-dom/client"; import { BrowserRouter } from "react-router-dom"; import App from "./App"; const rootElement = document.getElementById("root"); const root = ReactDOMClient.createRoot(rootElement); root.render( <StrictMode> <BrowserRouter> <App /> </BrowserRouter> </StrictMode> );
在这个文件中,我们导入了 BrowserRouter
组件,然后使用该组件包裹了 App
组件。现在,在这个 BrowserRouter
组件中,来自 react-router-dom
的其他组件和 hooks 就可以正常工作了。
BrowserRouter
是最常用的路由方式,即浏览器路由。官方文档也建议将 BrowserRouter
组件用于 Web 应用程序。除了这种方式,React Router 还支持其他几种路由方式:
HashRouter
:在路径前加入#
成为一个哈希值,Hash 模式的好处是不会因为刷新页面而找不到对应路径;MemoryRouter
:不存储 history,路由过程保存在内存中,适用于 React Native 这种非浏览器环境;NativeRouter
:配合 React Native 使用,多用于移动端;StaticRouter
:主要用于服务端渲染时。
(2)NavLink
在创建导航链接之前,先在App.tsx
组件中创建一个标题:
javascript
import "./styles.css"; export default function App() { return ( <div className="App"> <header> <h1>Hello World</h1> </header> </div> ); }
页面如下:
下面来创建三个导航链接,这些链接会指向App.tsx
中的一些路由。这时就需要导入 NavLink
组件,它是一个导航链接组件,类似于 HTML 中的标签。
NavLink
组件使用 to
来指定需要跳转的链接:
import { NavLink } from "react-router-dom"; import "./styles.css"; export default function App() { return ( <div className="App"> <header> <h1>Hello World</h1> </header> <nav> <NavLink to="">首页</NavLink> <NavLink to="product">产品</NavLink> <NavLink to="about">关于</NavLink> </nav> </div> ); }
可以看到,当点击这些导航链接时,网页的 URL 就会改变,跳转到对应的路由。
NavLink
是存在 active
状态的,所以可以为active
状态和非active
状态的导航链接添加样式:
.nav-active {
color: red; font-weight: bold;}
接下来为导航链接添加样式判断条件,选择性的为其添加nav-active
类:
import { NavLink } from "react-router-dom"; import "./styles.css"; export default function App() { return ( <div className="App"> <header> <h1>Hello World</h1> </header> <nav> <NavLink to="" className={({ isActive }) => isActive ? "nav-active" : void 0} > 首页 </NavLink> <NavLink to="product">产品</NavLink> <NavLink to="about">关于</NavLink> </nav> </div> ); }
当点击“首页”时,会跳转到首页,导航链接会变成 active
状态。这时,“首页”二字会变成红色,字体也会加粗:
(3)Link
Link
组件和 NavLink
组件的使用方式类似,例如在产品页面有一个返回首页的按钮,需要传递给 to
需要跳转的路径:
import { Link } from "react-router-dom"; import "./styles.css"; export default function Product() { return ( <div className="product"> <header> <Link to="/">返回首页</Link> </header> </div> ); }
如果需要对 Link
进行更多控制,也可以传递给 to
一个对象,在这个对象中,可以通过 search 属性来添加查询字符串或通过 hash
属性来传递 hash
值,例如:
import { Link } from "react-router-dom"; import "./styles.css"; export default function Settings() { return ( <div className="settings"> <header> <h1>Hello World</h1> <Link to={{ pathname: "/settings", search: "?sort=date", hash: "#hash" }} > 设置 </Link> </header> </div> ); }
点击“设置”时,路由就变成了:/settings?sort=date#hash
(4)Routes
下面来看看如何将路由映射为对应的页面(组件)。首先需要从 react-router-dom 中导入一个名为 Routes
的组件,它将包含可以在页面特定部分显示的所有不同的路由。
import { NavLink, Routes, Route } from "react-router-dom"; import Product from "./Product"; import "./styles.css"; export default function App() { return ( <div className="App"> <header> <h1>Hello World</h1> </header> <nav> <NavLink to="">首页</NavLink> <NavLink to="product">产品</NavLink> <NavLink to="about">关于</NavLink> </nav> <Routes> </Routes> </div> ); }
我们需要在 Routes
组件中使用 Route
组件来定义所有路由。该组件接受两个 props
:
Route
组件用于将应用的位置映射到不同的 React 组件。例如,当用户导航到 /product
路径时呈现 Product
组件,可以这样来写:
import { NavLink, Routes, Route } from "react-router-dom"; import Product from "./Product"; import About from "./About"; import Home from "./Home"; import Error from "./Error"; import "./styles.css"; export default function App() { return ( <div className="App"> <header> <h1>Hello World</h1> </header> <nav> <NavLink to="">首页</NavLink> <NavLink to="product">产品</NavLink> <NavLink to="about">关于</NavLink> </nav> <Routes> <Route path="/" element={<Home />} /> <Route path="/product" element={<Product />} /> <Route path="/about" element={<About />} /> <Route path="*" element={<Error />} /> </Routes> </div> ); }
当在地址栏输入一个没有定义的路由时,就会加载 Error
组件:
从上面的代码中可以看到,如果想要在所有 Route
都不匹配时就渲染 404 页面,只需将 404 页面对应的 Route
的 path
设置为 *
:
<Routes> <Route path="/" element={<Home />} /> <Route path="product" element={<Product />} /> <Route path="about" element={<About />} /> <Route path="*" element={<Error />} /> </Routes>
React Router v6 完全指南(下)https://developer.aliyun.com/article/1411424