React Router
Routing | React Router
1 JavaScript 与 TypeScript 版本的引入 React Router 的规则
在 JavaScript 中引入 React Router 的规则,与 TypeScript 版本的核心用法和引入方式基本一致,主要差异在于类型相关的代码(如类型定义、泛型等)在 JavaScript 中可以省略,其他核心 API 的导入和使用规则是相同的。
具体说明:
-
包的导入路径完全一致无论是 JavaScript 还是 TypeScript,React Router 的包结构和导入路径完全相同。例如:
// JavaScript 导入 import { BrowserRouter, Routes, Route, Link } from "react-router-dom";和 TypeScript 中的导入路径完全一样,没有区别。
-
核心 API 的使用规则一致路由的基本配置(如
<Routes>、<Route>嵌套、element属性、path匹配规则等)在 JavaScript 中写法相同,只是不需要指定类型:// JavaScript 示例 function App() {return (<BrowserRouter><Routes><Route path="/" element={<Home />} /><Route path="/about" element={<About />} /></Routes></BrowserRouter>); }这段代码在 TypeScript 中除了可能需要给组件添加类型定义外,结构完全一致。
-
钩子函数的使用一致如
useNavigate、useParams、useLocation等钩子,在 JavaScript 中直接使用即可,无需处理 TypeScript 的泛型参数:// JavaScript 中使用 useParams import { useParams } from "react-router-dom";function User() {const { id } = useParams(); // 直接解构,无需指定类型return <div>User ID: {id}</div>; }而 TypeScript 中可能需要指定参数类型(
useParams<{ id: string }>()),但 JavaScript 中可以省略。 -
唯一差异:类型相关代码TypeScript 文档中会包含类型定义(如
RouteObject类型、组件 props 类型等),这些在 JavaScript 中不需要考虑,直接按常规对象 / 函数使用即可。
总结:
只要忽略 TypeScript 文档中的类型注解、泛型、接口定义等类型相关代码,剩下的导入路径、API 用法、路由配置规则在 JavaScript 中完全适用,可以直接参考文档中的示例进行开发。
2 element 属性
在 React Router v6 中,<Route> 组件的 element 属性是必填项,用于指定当前路由匹配时要渲染的 React 元素(组件)。这是 v6 相比之前版本的重要变化(v5 中使用 component 或 render 属性,v6 已完全移除这些属性,统一使用 element)。
官方文档说明:
根据 React Router 官方文档,element 属性的作用是:
当路由匹配时,会渲染
element属性指定的 React 元素。它可以是任何有效的 React 节点(如组件、元素或片段)。
如果省略 element,路由匹配时将不会渲染任何内容,这也是为什么之前的代码中 <Route path="/todo" /> 无法正常工作的原因。
官方文档地址:
- 英文原版:React Router v6 - Route 组件
- 中文翻译版(非官方但准确):createRoutesFromElements |React 路由器
关键要点:
-
element的值必须是React 元素(即组件实例,如<Todo />),而不是组件本身(如Todo)。错误示例:<Route path="/todo" element={Todo} />(缺少<>和</>)正确示例:<Route path="/todo" element={<Todo />} /> -
可以渲染任何 React 节点,包括片段、文本或嵌套组件:
<Route path="/about" element={<>这是关于页面</>} /> <Route path="/user" element={<div><UserHeader /><UserContent /></div>} /> -
若需要动态渲染(如带参数的路由),
element中可以直接使用路由参数:<Route path="/user/:id" element={<UserProfile />} /> // 在 UserProfile 组件中通过 useParams() 获取 id
总之,element 是 v6 中 <Route> 组件的核心属性,用于定义路由对应的渲染内容,必须显式指定。
3 React Router 概述
React Router 是 React 生态中最流行的路由管理库,用于实现单页应用(SPA)的客户端路由。它允许开发者在不刷新页面的情况下,根据 URL 路径切换不同的组件视图,从而提供接近原生应用的流畅体验。
以下是对 React Router 的详细介绍:
1. 核心概念
- 路由(Route):定义 URL 路径与组件的映射关系,当 URL 匹配路径时,渲染对应的组件。
- 路径(Path):URL 中的路径部分,如
/about或/users/:id(动态参数)。 - 导航(Navigation):通过链接(Link)或编程方式(useNavigate)切换路由,避免页面刷新。
- 嵌套路由(Nested Routes):在父组件中嵌套子路由,实现复杂页面结构(如布局 + 内容区域)。
- 路由参数(Params):URL 中的动态部分(如
/users/:id中的id),用于传递数据。 - 查询参数(Query String):URL 中
?后的部分(如?page=1&sort=asc),用于筛选或分页。 - 路由守卫(Protected Routes):控制路由访问权限(如登录验证)。
2. 版本说明
React Router 目前主流版本为 v6(2021 年发布),与 v5 相比有较大改动(如移除 Switch、新增 Routes、简化 API 等)。本文以 v6 为例讲解。
3. 安装
使用 npm 或 yarn 安装核心包:
npm install react-router-dom # 适用于 web 应用
# 或
yarn add react-router-dom
4. 基本使用
步骤 1:包裹应用(Router Provider)
在入口文件(如 index.js)中,用 BrowserRouter 包裹整个应用,提供路由上下文:
import { BrowserRouter } from 'react-router-dom';ReactDOM.render(<BrowserRouter><App /></BrowserRouter>,document.getElementById('root')
);
BrowserRouter:使用 HTML5 History API(pushState/replaceState),URL 格式为/path(推荐)。HashRouter:使用 URL 中的哈希(#),格式为/#/path(兼容旧浏览器)。
步骤 2:定义路由(Routes 与 Route)
在组件中使用 Routes 和 Route 定义路由规则:
// App.js
import { Routes, Route } from 'react-router-dom';
import Home from './pages/Home';
import About from './pages/About';
import NotFound from './pages/NotFound';function App() {return (<div>{/* 路由容器:只渲染匹配的第一个路由 */}<Routes><Route path="/" element={<Home />} /> {/* 首页 */}<Route path="/about" element={<About />} /> {/* 关于页 */}<Route path="*" element={<NotFound />} /> {/* 404 页面(匹配所有未定义路径) */}</Routes></div>);
}
Routes:类似 v5 中的Switch,但功能更强,会自动选择最匹配的路由。Route:path为路由路径,element为匹配时渲染的组件。
步骤 3:导航(Link 与 NavLink)
使用 Link 实现无刷新导航(替代 <a> 标签,避免页面重载):
import { Link } from 'react-router-dom';function Navbar() {return (<nav><Link to="/">首页</Link><Link to="/about">关于</Link></nav>);
}
NavLink:是Link的增强版,可通过isActive状态为当前路由添加样式:jsx
<NavLink to="/" style={({ isActive }) => ({ color: isActive ? 'red' : 'black' })}>首页 </NavLink>
5. 进阶特性
5.1 动态路由参数
通过 :param 定义动态参数,使用 useParams 钩子获取:
// 定义路由
<Route path="/users/:id" element={<UserProfile />} />// UserProfile.js
import { useParams } from 'react-router-dom';function UserProfile() {const { id } = useParams(); // 获取 URL 中的 id 参数return <h1>用户 ID:{id}</h1>;
}
5.2 查询参数
使用 useSearchParams 钩子读写查询参数(类似 useState):
// 页面 URL:/products?category=book&page=1
import { useSearchParams } from 'react-router-dom';function Products() {const [searchParams, setSearchParams] = useSearchParams();const category = searchParams.get('category'); // "book"const page = searchParams.get('page'); // "1"const handlePageChange = (newPage) => {setSearchParams({ ...Object.fromEntries(searchParams), page: newPage });};return <button onClick={() => handlePageChange(2)}>下一页</button>;
}
5.3 嵌套路由
通过 Outlet 渲染子路由,实现布局嵌套:
// 父组件(布局)
function Dashboard() {return (<div><h1>控制台</h1><nav><Link to="profile">个人资料</Link><Link to="settings">设置</Link></nav>{/* 子路由将渲染在这里 */}<Outlet /></div>);
}// 路由定义
<Route path="/dashboard" element={<Dashboard />}><Route path="profile" element={<Profile />} /> {/* /dashboard/profile */}<Route path="settings" element={<Settings />} /> {/* /dashboard/settings */}<Route index element={<DashboardHome />} /> {/* 默认子路由:/dashboard */}
</Route>
Outlet:用于占位,子路由匹配时会替换此位置。index:指定父路由的默认子路由(当 URL 为父路径时渲染)。
5.4 编程式导航
使用 useNavigate 钩子实现代码触发导航:
import { useNavigate } from 'react-router-dom';function Login() {const navigate = useNavigate();const handleLogin = () => {// 登录成功后跳转到首页navigate('/');// 替换当前历史记录(无法回退到登录页)// navigate('/', { replace: true });// 回退一页// navigate(-1);};return <button onClick={handleLogin}>登录</button>;
}
5.5 路由守卫(Protected Routes)
通过自定义组件控制路由访问权限(如验证登录状态):
// PrivateRoute.js
import { Navigate, Outlet } from 'react-router-dom';function PrivateRoute() {const isAuthenticated = localStorage.getItem('token'); // 假设通过 token 判断登录// 如果已登录,渲染子路由;否则重定向到登录页return isAuthenticated ? <Outlet /> : <Navigate to="/login" />;
}// 使用方式
<Route element={<PrivateRoute />}><Route path="/dashboard" element={<Dashboard />} /> {/* 受保护的路由 */}
</Route>
6. 其他常用 API
useLocation:获取当前路由的位置信息(pathname、search、state等)。useNavigate:编程式导航(见 5.4)。useRoutes:通过对象配置路由(替代 JSX 写法)。Navigate:组件式重定向(如<Navigate to="/" replace />)。
7. 总结
React Router 是 React 单页应用路由管理的标准解决方案,核心功能包括:
- 声明式路由定义(
Routes/Route)。 - 无刷新导航(
Link/NavLink)。 - 动态参数与查询参数处理。
- 嵌套路由与布局管理。
- 编程式导航与路由守卫。
掌握 React Router 是开发复杂 React 应用的必备技能,建议结合官方文档(reactrouter.com)深入学习。
