当前位置: 首页 > news >正文

React学习教程,从入门到精通,React Router 语法知识点及使用方法详解(28)

React Router 语法知识点及使用方法详解


📌 当前环境说明

本文基于 React Router v5 编写(因你提供的知识点如 withRouterSwitchPrompt 等属于 v5 特性)。
若使用 React Router v6,部分 API 已废弃或重构(如 Switch → Routes, withRouter → hooks, Prompt → unstable_usePrompt 等)。


一、React Router 基础路由配置

✅ 1. 安装 React Router

npm install react-router-dom@5

✅ 2. 简单示例:网站列表(基础路由)

🎯 功能说明:

  • 首页 / 显示网站列表
  • 点击跳转到对应网站详情 /site/:id
  • 使用 BrowserRouter, Route, Link, Switch

🧩 代码示例:

// App.js
import React from 'react';
import { BrowserRouter as Router, Route, Link, Switch } from 'react-router-dom';// 模拟数据
const sites = [{ id: 1, name: 'Google', url: 'https://google.com' },{ id: 2, name: 'GitHub', url: 'https://github.com' },{ id: 3, name: 'React', url: 'https://reactjs.org' },
];// 首页组件:显示网站列表
function Home() {return (<div><h2>🌐 网站列表</h2><ul>{sites.map(site => (<li key={site.id}>{/* 使用 Link 进行客户端导航,不刷新页面 */}<Link to={`/site/${site.id}`}>{site.name}</Link></li>))}</ul></div>);
}// 详情页组件:根据 URL 参数显示网站信息
function SiteDetail({ match }) {// match.params.id 获取动态路由参数const site = sites.find(s => s.id === parseInt(match.params.id));if (!site) return <h3>网站不存在</h3>;return (<div><h2>📌 {site.name} 详情页</h2><p>网址:<a href={site.url} target="_blank" rel="noopener noreferrer">{site.url}</a></p><Link to="/">⬅ 返回首页</Link></div>);
}// 主应用组件
function App() {return (<Router><div style={{ padding: '20px' }}><h1>🔗 React Router 网站导航系统</h1><hr />{/* Switch 确保只匹配第一个符合条件的路由 */}<Switch>{/* 精确匹配首页 */}<Route exact path="/" component={Home} />{/* 动态路由匹配详情页 */}<Route path="/site/:id" component={SiteDetail} />{/* 404 页面 */}<Route><h3>⛔ 页面未找到</h3><Link to="/">返回首页</Link></Route></Switch></div></Router>);
}export default App;

二、路由组件的属性(props)

当组件通过 Route 渲染时,会自动注入以下 props:

  • history:用于编程式导航(如 history.push()
  • location:当前 URL 信息(如 pathname, search, state
  • match:匹配信息(如 params, path, url

🧩 示例:打印路由属性

function DebugRoute({ history, location, match }) {return (<div><h3>🔍 路由调试信息</h3><pre>{JSON.stringify({ history: 'object', location, match }, null, 2)}</pre></div>);
}// 在路由中使用
<Route path="/debug" component={DebugRoute} />

三、Switch 组件

Switch 只渲染第一个匹配的 RouteRedirect,避免多个路由同时激活。

🧩 示例:不使用 Switch 的问题

{/* ❌ 不使用 Switch —— 可能多个组件同时渲染 */}
<Route path="/" component={Home} />
<Route path="/about" component={About} />
{/* 当访问 /about 时,两个都会匹配(因为 / 包含在 /about 中)*/}

✅ 正确用法:

<Switch><Route exact path="/" component={Home} /><Route path="/about" component={About} /><Route path="/contact" component={Contact} />{/* 默认 fallback */}<Route component={NotFound} />
</Switch>

四、路由匹配 matchPath()

用于在组件外或逻辑中手动匹配路径(如在 Redux 中判断当前路由)。

🧩 语法:

import { matchPath } from 'react-router-dom';const match = matchPath("/users/123", {path: "/users/:id",exact: true,strict: false
});

🧩 示例:在组件外判断路由

import { matchPath } from 'react-router-dom';function App() {const currentPath = window.location.pathname;const userMatch = matchPath(currentPath, {path: "/user/:id",exact: true});if (userMatch) {console.log("当前是用户页,ID:", userMatch.params.id);}return (<Router>{/* ... */}</Router>);
}

五、静态路由 vs 动态路由

✅ 静态路由

路径固定,无参数。

<Route path="/about" component={About} />
<Route path="/contact" component={Contact} />

✅ 动态路由

路径含参数,如 :id, :name

<Route path="/user/:id" component={UserProfile} />
<Route path="/category/:categoryName" component={CategoryPage} />

🧩 示例:动态路由 + 参数获取

function UserProfile({ match }) {const { id } = match.params;return <h2>用户ID:{id}</h2>;
}// 支持多个参数
<Route path="/post/:year/:month/:slug" component={BlogPost} />function BlogPost({ match }) {const { year, month, slug } = match.params;return (<div><h2>文章:{slug}</h2><p>发布于 {year} 年 {month} 月</p></div>);
}

六、各种路由器(Routers)

✅ 1. BrowserRouter(最常用)

使用 HTML5 History API(pushState, replaceState),URL 看起来干净:http://example.com/about

import { BrowserRouter } from 'react-router-dom';<BrowserRouter><App />
</BrowserRouter>

✅ 2. HashRouter

使用 URL hash(#),兼容老浏览器,URL 如:http://example.com/#/about

import { HashRouter } from 'react-router-dom';<HashRouter><App />
</HashRouter>

✅ 3. MemoryRouter

用于测试或非浏览器环境(如 React Native 之外的场景),URL 不反映在地址栏。

import { MemoryRouter } from 'react-router-dom';<MemoryRouter initialEntries={['/home', '/about']} initialIndex={0}><App />
</MemoryRouter>

✅ 4. NativeRouter(React Native 专用)

用于 React Native 应用,不在 Web 环境使用。

// 仅在 React Native 中
import { NativeRouter } from 'react-router-native';

✅ 5. StaticRouter(服务端渲染 SSR)

用于 Node.js 服务端渲染,需传入 locationcontext

// server.js (Express 示例)
import { StaticRouter } from 'react-router-dom';app.get('*', (req, res) => {const context = {};const markup = ReactDOMServer.renderToString(<StaticRouter location={req.url} context={context}><App /></StaticRouter>);if (context.url) {res.redirect(301, context.url);} else {res.send(`<!DOCTYPE html><html><body><div id="root">${markup}</div><script src="/client.js"></script></body></html>`);}
});

七、React Router 特性组件

✅ 1. Prompt 组件 —— 离开页面确认

在用户离开当前页面前弹出确认框(如表单未保存)。

import { Prompt } from 'react-router-dom';function ContactForm() {const [isBlocking, setIsBlocking] = useState(false);return (<div>{/* 当 isBlocking 为 true 时,离开页面会弹出提示 */}<Promptwhen={isBlocking}message="你有未保存的内容,确定要离开吗?"/><textareaonChange={(e) => setIsBlocking(e.target.value.length > 0)}placeholder="输入内容..."/><button onClick={() => setIsBlocking(false)}>提交</button></div>);
}

⚠️ 注意:现代浏览器对 Prompt 限制较多,部分浏览器可能忽略自定义消息。


✅ 2. withRouter 高阶组件(HOC)

history, location, match 注入到非路由组件中。

import { withRouter } from 'react-router-dom';function BackButton({ history }) {return (<button onClick={() => history.goBack()}>⬅ 返回上一页</button>);
}// 包装后即可获得路由属性
export default withRouter(BackButton);

在类组件中使用:

class UserProfile extends React.Component {handleEdit = () => {this.props.history.push(`/user/${this.props.match.params.id}/edit`);};render() {return (<div><h2>用户页</h2><button onClick={this.handleEdit}>编辑</button></div>);}
}export default withRouter(UserProfile);

💡 v6 替代方案:使用 useNavigate, useLocation, useParams hooks。


✅ 3. Redirect 组件 —— 重定向

用于登录跳转、页面迁移、权限控制等。

基本用法:

<Redirect to="/login" />

带状态跳转:

<Redirectto={{pathname: "/login",state: { from: props.location } // 传递来源页,登录后可跳回}}
/>

条件重定向示例:

function PrivateRoute({ component: Component, isAuthenticated, ...rest }) {return (<Route{...rest}render={props =>isAuthenticated ? (<Component {...props} />) : (<Redirect to={{ pathname: "/login", state: { from: props.location } }} />)}/>);
}// 使用
<PrivateRoute path="/dashboard" component={Dashboard} isAuthenticated={userLoggedIn} />

八、综合性案例:带权限控制的后台管理系统

// App.js - 综合案例
import React, { useState } from 'react';
import {BrowserRouter as Router,Route,Link,Switch,Redirect,Prompt,withRouter
} from 'react-router-dom';// 模拟登录状态
const fakeAuth = {isAuthenticated: false,authenticate(cb) {fakeAuth.isAuthenticated = true;setTimeout(cb, 100); // 模拟异步},signout(cb) {fakeAuth.isAuthenticated = false;setTimeout(cb, 100);}
};// 登录页
function Login({ history }) {const [redirectToReferrer, setRedirectToReferrer] = useState(false);const login = () => {fakeAuth.authenticate(() => {setRedirectToReferrer(true);});};if (redirectToReferrer) {return <Redirect to="/dashboard" />;}return (<div><h2>🔒 登录</h2><button onClick={login}>登录系统</button></div>);
}// 仪表盘(需登录)
function Dashboard() {const [formChanged, setFormChanged] = useState(false);return (<div><h2>📊 仪表盘</h2><Promptwhen={formChanged}message="有未保存的更改,确定离开?"/><p>模拟表单:</p><input type="text" onChange={() => setFormChanged(true)} /><button onClick={() => setFormChanged(false)}>保存</button></div>);
}// 设置页
function Settings() {return <h2>⚙️ 设置页面</h2>;
}// 导航栏(使用 withRouter 获取 history)
const Navigation = withRouter(({ history, location }) => (<nav><ul style={{ display: 'flex', gap: '1rem', marginBottom: '1rem' }}><li><Link to="/dashboard">仪表盘</Link></li><li><Link to="/settings">设置</Link></li><li>{fakeAuth.isAuthenticated ? (<button onClick={() => {fakeAuth.signout(() => history.push('/'));}}>退出登录</button>) : (<Link to="/login">登录</Link>)}</li></ul><p>📍 当前路径:{location.pathname}</p></nav>
));// 私有路由组件
function PrivateRoute({ component: Component, ...rest }) {return (<Route{...rest}render={props =>fakeAuth.isAuthenticated ? (<Component {...props} />) : (<Redirectto={{pathname: "/login",state: { from: props.location }}}/>)}/>);
}// 主应用
function App() {return (<Router><div style={{ padding: '20px' }}><h1>🔐 后台管理系统</h1><Navigation /><Switch><Route exact path="/" render={() => <h2>欢迎!请登录进入系统</h2>} /><Route path="/login" component={Login} /><PrivateRoute path="/dashboard" component={Dashboard} /><PrivateRoute path="/settings" component={Settings} /><Route render={() => <h3>⛔ 404 页面不存在</h3>} /></Switch></div></Router>);
}export default App;

九、本章小结

知识点作用说明
BrowserRouter使用 HTML5 History API,推荐用于现代 Web 应用
Route定义路径与组件映射关系
Link声明式导航,替代 <a> 标签
Switch只渲染第一个匹配路由,避免冲突
match.params获取动态路由参数(如 /user/:id
Redirect重定向到其他路由,常用于登录跳转
Prompt离开页面前确认,防止数据丢失
withRouter非路由组件获取路由属性(v5),v6 用 hooks 替代
matchPath手动匹配路径,适用于逻辑判断
HashRouter兼容老浏览器,URL 含 #
StaticRouter服务端渲染专用

🚀 升级建议(React Router v6)

若你计划使用 v6,请注意:

  • SwitchRoutes
  • Route componentRoute element={<Component />}
  • withRouteruseNavigate(), useLocation(), useParams()
  • Promptunstable_usePrompt(实验性)或自定义逻辑
  • exact 属性默认启用

✅ 以上内容涵盖 React Router v5 核心知识点 + 详细案例 + 综合实战,可直接用于项目开发或学习参考。

http://www.dtcms.com/a/398428.html

相关文章:

  • Docker Compose 从入门到实践
  • D3.js 与数据可视化
  • RNA-seq分析之最佳cutoff(TCGA版)
  • 浏览器直接进入网站的注意事项钢筋网片价格
  • scrapy-redis项目:爬取某网站图书信息
  • (论文速读)DiffBlender:可组合和通用的多模态文本到图像扩散模型
  • 第三方网站测试工具:【Postman使用基础指南】
  • Pytest+requests进行接口自动化测试5.0(5种assert断言的封装 + pymysql)
  • C# MVC 模型绑定全解析:从基础机制到自定义绑定器实战指南
  • 企业网站网页设计专业的团队网站建设
  • 网站建设可上传视频的wordpress 数据库类型
  • 广州南沙区建设和交通局网站个人建立网站要多少钱
  • Vue3 》》vite》》vite-plugin-mock mock 模拟数据 ,loadEnv
  • 宝塔面板搭建RustDesk教程:告别命令行,一键拥有私有远程桌面
  • Docker + IDEA 一键部署!
  • Rust开源HyperSwitch实战指南
  • Chrome性能优化指南
  • Chrome高危类型混淆0-Day漏洞(CVE-2025-10585)技术分析
  • 教做面点的网站广州百度竞价托管
  • 网站推广方案合肥房产网安居客
  • 【算法专题训练】24、单调栈
  • 【开题答辩全过程】以 IRWT考试预约系统为例,包含答辩的问题和答案
  • 在字典和列表相互嵌套的结构体中搜索指定元素
  • 文献阅读 | iMetaMed | FigureYa:一个标准化可视化框架,用于增强生物医学数据解释和研究效率
  • wordpress自由拖拽同ip网站做排名seo
  • 面向运动障碍患者的语音识别新突破:零样本实时专家混合自适应方法详解
  • 校园网站建设的维护制作触屏版网站开发
  • 零衍门户组件联邦模式:重新定义组件开发新体验!
  • 【Web前端|第一篇】HTML、CSS与JavaScript
  • 有手机网站了还要微网站吗所有的网站都要用htmlu做吗