React从基础入门到高级实战:React 核心技术 - React Router:路由管理
React Router:路由管理
在现代 Web 应用开发中,路由管理 是构建多页面或单页应用(SPA)的核心技术之一。React Router 是 React 生态中最受欢迎的路由管理库,它为开发者提供了强大的工具来实现页面导航、动态路由和权限控制等功能。React Router v6 是其最新版本,相较于之前的版本,它带来了更简洁的 API、更灵活的嵌套路由支持以及更强大的导航工具,显著提升了开发体验。
本文专为希望实现多页面应用的开发者设计,内容涵盖 React Router v6 的安装与配置、核心路由组件、动态路由、导航方式、嵌套路由和路由守卫等核心主题。我们将通过一个简单的电商网站案例(包含首页、商品列表和详情页)以及一个练习任务(实现受保护的用户中心),帮助你深入掌握 React Router v6 的核心技能。
文章目标
- 理解 React Router v6 的安装和基本配置。
- 掌握核心路由组件(如
<Routes>
、<Route>
)的使用。 - 实现动态路由和查询参数的处理。
- 学会使用导航组件(
<Link>
、<NavLink>
)和 Hook(useNavigate
)。 - 探索嵌套路由和路由守卫的实现方法。
- 通过电商网站案例和练习任务巩固所学知识。
1. React Router v6 简介
1.1 什么是 React Router?
React Router 是一个专为 React 应用设计的路由管理库,它允许开发者根据 URL 动态渲染不同的组件,从而实现页面导航和切换。在单页应用(SPA)中,React Router 通过客户端路由管理页面的显示,无需刷新浏览器即可实现流畅的页面跳转。它是 React 生态中不可或缺的一部分,尤其适用于需要多页面结构的复杂应用。
1.2 为什么选择 React Router v6?
React Router v6 是 React Router 的最新版本,相较于 v5 和更早的版本,它引入了许多重要改进和新特性:
- 更简洁的 API:移除了
<Switch>
组件,改为使用<Routes>
和<Route>
的组合,语法更直观。 - 更强大的嵌套路由:通过
<Outlet>
组件实现灵活的布局管理。 - 动态路由增强:支持相对路径和更便捷的参数化路由。
- 内置导航 Hook:提供了
useNavigate
、useParams
等 Hook,简化路由操作。 - 性能优化:路由匹配和渲染更加高效。
这些新特性使得 React Router v6 成为 2025 年及未来构建现代 Web 应用的首选工具,尤其是在 React 19 的新特性(如 Server Components)逐渐普及的背景下。
2. 安装与配置 React Router v6
2.1 安装
在 React 项目中安装 React Router v6,只需运行以下命令:
npm install react-router-dom@6
注意:确保指定版本
@6
,以避免安装旧版本或其他不兼容的版本。
2.2 基本配置
React Router v6 使用 <BrowserRouter>
作为路由容器,通常在应用的根组件中进行配置。<BrowserRouter>
利用 HTML5 History API 管理路由,支持干净的 URL(如 /about
而不是 #/about
)。
代码示例:
// main.jsx
import React from 'react';
import ReactDOM from 'react-dom/client';
import { BrowserRouter } from 'react-router-dom';
import App from './App';ReactDOM.createRoot(document.getElementById('root')).render(<BrowserRouter><App /></BrowserRouter>
);
<BrowserRouter>
:最常用的路由容器,适合大多数 Web 应用。- 其他路由器选项:
<HashRouter>
:使用 URL 的#
部分管理路由,适合静态文件部署。<MemoryRouter>
:将路由存储在内存中,适用于测试或服务器端渲染(SSR)场景。
在 App
组件中,我们将定义具体的路由规则。
3. 核心路由组件
React Router v6 的核心组件包括 <Routes>
和 <Route>
,它们共同定义了应用的路由结构。
3.1 <Routes>
和 <Route>
<Routes>
:路由容器的根组件,用于包裹所有<Route>
。<Route>
:定义单个路由规则,通过path
属性匹配 URL,通过element
属性指定渲染的组件。
代码示例:
// App.jsx
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 (<Routes><Route path="/" element={<Home />} /><Route path="/about" element={<About />} /><Route path="*" element={<NotFound />} /></Routes>);
}
path="/"
: 匹配根路径,渲染Home
组件。path="/about"
: 匹配/about
路径,渲染About
组件。path="*"
: 通配符,匹配所有未定义的路径,渲染NotFound
组件(404 页面)。
v6 新特性:相比 v5 的
<Switch>
,<Routes>
更加智能,能够自动匹配最佳路由,并支持嵌套路由的优化。
3.2 动态路由
动态路由允许根据 URL 中的参数渲染不同的内容。例如,/product/1
和 /product/2
可以渲染同一个组件,但显示不同的商品详情。
代码示例:
// App.jsx
import { Route } from 'react-router-dom';
import ProductDetail from './pages/ProductDetail';function App() {return (<Routes><Route path="/product/:id" element={<ProductDetail />} /></Routes>);
}
:id
:动态参数,表示 URL 中的变量部分。- 示例 URL:
/product/1
会将id
设置为"1"
。
在 ProductDetail
组件中,使用 useParams
Hook 获取参数:
// pages/ProductDetail.jsx
import { useParams } from 'react-router-dom';function ProductDetail() {const { id } = useParams();return <h1>商品 ID: {id}</h1>;
}
useParams
:返回一个对象,包含所有动态参数。
3.3 查询参数
查询参数通过 URL 的 ?key=value
形式传递,常用于筛选、搜索等场景。React Router v6 提供了 useSearchParams
Hook 来处理查询参数。
代码示例:
// pages/ProductList.jsx
import { useSearchParams } from 'react-router-dom';function ProductList() {const [searchParams, setSearchParams] = useSearchParams();const category = searchParams.get('category');return (<div><h1>商品列表 - {category || '全部'}</h1><button onClick={() => setSearchParams({ category: 'electronics' })}>筛选电子产品</button></div>);
}
useSearchParams
:返回一个数组,包含当前查询参数对象和更新函数。searchParams.get('category')
:获取category
参数的值。setSearchParams
:更新 URL 的查询参数,例如点击按钮后 URL 变为/products?category=electronics
。
4. 导航:Link、NavLink 与 useNavigate
导航是路由管理的核心功能之一,React Router v6 提供了多种方式来实现页面跳转。
4.1 <Link>
<Link>
组件用于创建导航链接,点击时跳转到指定路径,避免页面刷新。
代码示例:
import { Link } from 'react-router-dom';function Navbar() {return (<nav><Link to="/">首页</Link> |{' '}<Link to="/about">关于我们</Link></nav>);
}
to
属性:指定跳转的目标路径。<Link>
渲染为<a>
标签,但通过 React Router 内部机制实现客户端导航。
4.2 <NavLink>
<NavLink>
是 <Link>
的增强版,可以根据当前路径动态调整样式,例如高亮当前导航项。
代码示例:
import { NavLink } from 'react-router-dom';function Navbar() {return (<nav><NavLinkto="/"className={({ isActive }) => (isActive ? 'active' : '')}>首页</NavLink>{' '}|{' '}<NavLinkto="/about"className={({ isActive }) => (isActive ? 'active' : '')}>关于我们</NavLink></nav>);
}
className
:接受一个函数,参数isActive
表示当前路径是否匹配。- 示例 CSS:
.active {color: red;font-weight: bold;
}
4.3 useNavigate
Hook
useNavigate
Hook 允许在组件内部以编程方式导航,适用于事件驱动的场景(如按钮点击、表单提交)。
代码示例:
import { useNavigate } from 'react-router-dom';function Login() {const navigate = useNavigate();const handleLogin = () => {// 模拟登录逻辑navigate('/dashboard');};return <button onClick={handleLogin}>登录</button>;
}
navigate('/dashboard')
:跳转到/dashboard
。navigate(-1)
:返回上一页,类似浏览器的“后退”按钮。navigate('/path', { replace: true })
:替换当前历史记录,而不是添加新记录。
v6 新特性:
useNavigate
替代了 v5 的useHistory
,API 更直观且功能更强大。
5. 嵌套路由与路由守卫
5.1 嵌套路由
嵌套路由允许在父路由中定义子路由,常用于实现包含公共布局的页面(如导航栏 + 主内容)。
代码示例:
// App.jsx
import { Routes, Route, Outlet } from 'react-router-dom';
import Layout from './components/Layout';
import Home from './pages/Home';
import Dashboard from './pages/Dashboard';
import Settings from './pages/Settings';function App() {return (<Routes><Route path="/" element={<Layout />}><Route index element={<Home />} /><Route path="dashboard" element={<Dashboard />} /><Route path="settings" element={<Settings />} /></Route></Routes>);
}// components/Layout.jsx
import { Outlet } from 'react-router-dom';function Layout() {return (<div><nav>导航栏</nav><main><Outlet /> {/* 子路由渲染位置 */}</main></div>);
}
<Route path="/" element={<Layout />}>
:父路由,渲染Layout
组件。<Outlet />
:子路由的占位符,指定子组件的渲染位置。<Route index>
:默认子路由,匹配父路径/
时渲染。
v6 新特性:
<Outlet>
替代了 v5 中手动传递children
,嵌套路由更加简洁。
5.2 路由守卫
路由守卫用于保护某些路由,确保用户在访问受限页面前满足特定条件(如已登录)。React Router v6 没有内置的守卫组件,但可以通过自定义组件实现。
实现方式:
import { Navigate, useLocation } from 'react-router-dom';function ProtectedRoute({ children }) {const isAuthenticated = false; // 模拟认证状态const location = useLocation();if (!isAuthenticated) {return <Navigate to="/login" state={{ from: location }} replace />;}return children;
}// 使用
<Routepath="/dashboard"element={<ProtectedRoute><Dashboard /></ProtectedRoute>}
/>
ProtectedRoute
:检查认证状态的自定义组件。<Navigate>
:未认证时重定向到/login
。state={{ from: location }}
:记录来源路径,登录后可返回。
6. 实践案例:电商网站
我们将通过一个简单的电商网站案例,综合应用以上知识。网站包含以下页面:
- 首页:欢迎页面。
- 商品列表:展示商品,支持筛选。
- 商品详情:根据商品 ID 显示详情。
6.1 项目结构
src/
├── pages/
│ ├── Home.jsx
│ ├── ProductList.jsx
│ ├── ProductDetail.jsx
├── components/
│ ├── Navbar.jsx
├── App.jsx
├── main.jsx
6.2 路由配置
// App.jsx
import { Routes, Route } from 'react-router-dom';
import Home from './pages/Home';
import ProductList from './pages/ProductList';
import ProductDetail from './pages/ProductDetail';
import Navbar from './components/Navbar';function App() {return (<div><Navbar /><Routes><Route path="/" element={<Home />} /><Route path="/products" element={<ProductList />} /><Route path="/product/:id" element={<ProductDetail />} /></Routes></div>);
}
6.3 导航栏
// components/Navbar.jsx
import { NavLink } from 'react-router-dom';function Navbar() {return (<nav><NavLink to="/" className={({ isActive }) => (isActive ? 'active' : '')}>首页</NavLink>{' '}|{' '}<NavLinkto="/products"className={({ isActive }) => (isActive ? 'active' : '')}>商品列表</NavLink></nav>);
}
6.4 首页
// pages/Home.jsx
function Home() {return <h1>欢迎来到电商网站</h1>;
}
6.5 商品列表
// pages/ProductList.jsx
import { useSearchParams } from 'react-router-dom';function ProductList() {const [searchParams, setSearchParams] = useSearchParams();const category = searchParams.get('category');const products = [{ id: 1, name: '手机', category: 'electronics' },{ id: 2, name: '书籍', category: 'books' },];const filteredProducts = category? products.filter((p) => p.category === category): products;return (<div><h1>商品列表 - {category || '全部'}</h1><button onClick={() => setSearchParams({ category: 'electronics' })}>电子产品</button><button onClick={() => setSearchParams({ category: 'books' })}>书籍</button><button onClick={() => setSearchParams({})}>全部</button><ul>{filteredProducts.map((product) => (<li key={product.id}><a href={`/product/${product.id}`}>{product.name}</a></li>))}</ul></div>);
}
6.6 商品详情
// pages/ProductDetail.jsx
import { useParams, useNavigate } from 'react-router-dom';function ProductDetail() {const { id } = useParams();const navigate = useNavigate();const products = {1: { name: '手机', price: 2999 },2: { name: '书籍', price: 59 },};const product = products[id] || { name: '未知商品', price: 0 };return (<div><h1>{product.name}</h1><p>价格: ¥{product.price}</p><button onClick={() => navigate('/products')}>返回列表</button></div>);
}
这个案例展示了动态路由(/product/:id
)、查询参数(筛选商品)和导航(<NavLink>
和 useNavigate
)的实际应用。
7. 练习:添加受保护的用户中心
现在,请尝试为电商网站添加一个受保护的 用户中心,包含以下要求:
- 创建
/user
路由,渲染UserCenter
组件。 - 使用
ProtectedRoute
保护该路由,仅允许已登录用户访问。 - 在
UserCenter
中添加一个嵌套路由/user/profile
,渲染Profile
组件。
参考实现
7.1 更新路由配置
// App.jsx
import { Routes, Route } from 'react-router-dom';
import Home from './pages/Home';
import ProductList from './pages/ProductList';
import ProductDetail from './pages/ProductDetail';
import UserCenter from './pages/UserCenter';
import Profile from './pages/Profile';
import ProtectedRoute from './components/ProtectedRoute';
import Navbar from './components/Navbar';function App() {return (<div><Navbar /><Routes><Route path="/" element={<Home />} /><Route path="/products" element={<ProductList />} /><Route path="/product/:id" element={<ProductDetail />} /><Routepath="/user"element={<ProtectedRoute><UserCenter /></ProtectedRoute>}><Route path="profile" element={<Profile />} /></Route></Routes></div>);
}
7.2 实现 ProtectedRoute
// components/ProtectedRoute.jsx
import { Navigate } from 'react-router-dom';function ProtectedRoute({ children }) {const isAuthenticated = localStorage.getItem('token'); // 模拟认证return isAuthenticated ? children : <Navigate to="/login" replace />;
}
7.3 用户中心
// pages/UserCenter.jsx
import { Link, Outlet } from 'react-router-dom';function UserCenter() {return (<div><h1>用户中心</h1><nav><Link to="/user/profile">编辑资料</Link></nav><Outlet /> {/* 渲染子路由 */}</div>);
}
7.4 个人资料页
// pages/Profile.jsx
function Profile() {return <h2>个人资料页面</h2>;
}
7.5 更新导航栏
// components/Navbar.jsx
import { NavLink } from 'react-router-dom';function Navbar() {return (<nav><NavLink to="/" className={({ isActive }) => (isActive ? 'active' : '')}>首页</NavLink>{' '}|{' '}<NavLinkto="/products"className={({ isActive }) => (isActive ? 'active' : '')}>商品列表</NavLink>{' '}|{' '}<NavLinkto="/user"className={({ isActive }) => (isActive ? 'active' : '')}>用户中心</NavLink></nav>);
}
测试步骤
- 未登录时(
localStorage.getItem('token')
为 null),访问/user
会跳转到/login
。 - 模拟登录(
localStorage.setItem('token', '123')
),即可访问/user
和/user/profile
。
8. 总结与进阶建议
React Router v6 是一个功能强大且灵活的路由管理工具,通过 <Routes>
、<Route>
、<Link>
等组件以及 useNavigate
、useParams
等 Hook,开发者可以轻松实现多页面应用的导航和权限控制。本文通过电商网站案例和用户中心练习,展示了 React Router v6 的核心功能及其新特性(如 <Outlet>
和简化的 API)。
进阶建议
- 数据加载器(Data Loaders):探索 React Router v6 的数据加载功能,提升页面加载性能。
- 状态管理集成:结合 Redux 或 Context API,实现更复杂的路由逻辑。
希望这篇教程能为你的 React 开发之旅提供坚实的基础!如果有任何问题,欢迎交流。
以下是一个完整的 React Router v6 电商网站示例代码,供参考:
<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>电商网站 - React Router v6</title><script src="https://cdn.jsdelivr.net/npm/react@18/umd/react.development.js"></script><script src="https://cdn.jsdelivr.net/npm/react-dom@18/umd/react-dom.development.js"></script><script src="https://cdn.jsdelivr.net/npm/react-router-dom@6/dist/umd/react-router-dom.development.js"></script><script src="https://cdn.jsdelivr.net/npm/@babel/standalone/babel.min.js"></script><style>nav { margin-bottom: 20px; }.active { color: red; font-weight: bold; }button { margin: 0 5px; }</style>
</head>
<body><div id="root"></div><script type="text/babel">const { BrowserRouter, Routes, Route, Link, NavLink, useParams, useNavigate, useSearchParams, Outlet, Navigate } = ReactRouterDOM;function ProtectedRoute({ children }) {const isAuthenticated = localStorage.getItem('token');return isAuthenticated ? children : <Navigate to="/login" replace />;}function Navbar() {return (<nav><NavLink to="/" className={({ isActive }) => (isActive ? 'active' : '')}>首页</NavLink> |{' '}<NavLink to="/products" className={({ isActive }) => (isActive ? 'active' : '')}>商品列表</NavLink> |{' '}<NavLink to="/user" className={({ isActive }) => (isActive ? 'active' : '')}>用户中心</NavLink></nav>);}function Home() {return <h1>欢迎来到电商网站</h1>;}function ProductList() {const [searchParams, setSearchParams] = useSearchParams();const category = searchParams.get('category');const products = [{ id: 1, name: '手机', category: 'electronics' },{ id: 2, name: '书籍', category: 'books' },];const filteredProducts = category ? products.filter(p => p.category === category) : products;return (<div><h1>商品列表 - {category || '全部'}</h1><button onClick={() => setSearchParams({ category: 'electronics' })}>电子产品</button><button onClick={() => setSearchParams({ category: 'books' })}>书籍</button><button onClick={() => setSearchParams({})}>全部</button><ul>{filteredProducts.map(product => (<li key={product.id}><Link to={`/product/${product.id}`}>{product.name}</Link></li>))}</ul></div>);}function ProductDetail() {const { id } = useParams();const navigate = useNavigate();const products = {1: { name: '手机', price: 2999 },2: { name: '书籍', price: 59 },};const product = products[id] || { name: '未知商品', price: 0 };return (<div><h1>{product.name}</h1><p>价格: ¥{product.price}</p><button onClick={() => navigate('/products')}>返回列表</button></div>);}function UserCenter() {return (<div><h1>用户中心</h1><nav><Link to="/user/profile">编辑资料</Link></nav><Outlet /></div>);}function Profile() {return <h2>个人资料页面</h2>;}function Login() {const navigate = useNavigate();const handleLogin = () => {localStorage.setItem('token', '123');navigate('/user');};return <button onClick={handleLogin}>登录</button>;}function App() {return (<div><Navbar /><Routes><Route path="/" element={<Home />} /><Route path="/products" element={<ProductList />} /><Route path="/product/:id" element={<ProductDetail />} /><Route path="/login" element={<Login />} /><Route path="/user" element={<ProtectedRoute><UserCenter /></ProtectedRoute>}><Route path="profile" element={<Profile />} /></Route></Routes></div>);}const root = ReactDOM.createRoot(document.getElementById('root'));root.render(<BrowserRouter><App /></BrowserRouter>);</script>
</body>
</html>
运行这段代码,你将得到一个完整的电商网站示例,包含所有功能点。祝你学习愉快!
相关文章:
React从基础入门到高级实战:React 核心技术 - React Router:路由管理
React Router:路由管理 在现代 Web 应用开发中,路由管理 是构建多页面或单页应用(SPA)的核心技术之一。React Router 是 React 生态中最受欢迎的路由管理库,它为开发者提供了强大的工具来实现页面导航、动态路由和权限…...

【深度学习】损失“三位一体”——从 Fisher 的最大似然到 Shannon 的交叉熵再到 KL 散度,并走进 PET·P-Tuning微调·知识蒸馏的实战
一页速览: 1912 Fisher 用最大似然把「让数据出现概率最高」变成参数学习; 1948 Shannon 把交叉熵解释成「最短平均编码长度」; 1951 Kullback-Leibler 用相对熵量化「多余信息」。 三条历史线落到今天深度学习同一个损失——交叉熵。 也…...

5 分钟速通密码学!
让我们开始第一部分:密码学基础 (Cryptography Basics)。 第一部分:密码学基础 (Cryptography Basics) 1. 什么是密码学? 想象一下,在古代战争中,将军需要向远方的部队传递作战指令。如果直接派人送信,信…...

Linux——IP协议
1. 现实意义 • IP协议:提供一种能力,把数据报从主机A跨网络送到主机B • TCP/IP协议:核心功能,把数据100%可靠的从主机A跨网络送到主机B 注:TCP协议负责百分百可靠,通过三次握手、滑动窗口、拥塞控制、延…...
Lua 脚本在 Redis 中的运用-24 (使用 Lua 脚本实现原子计数器)
实践练习:使用 Lua 脚本实现原子计数器 实现原子计数器是许多应用程序中的常见需求,例如跟踪网站访问量、限制 API 请求或管理库存。虽然 Redis 提供了 INCR 命令用于递增整数,但在复杂场景或与其他操作结合时直接使用它可能并不足够。本课程探讨了如何在 Redis 中利用 Lua…...

Linux信号量(32)
文章目录 前言一、POSIX 信号量信号量的基础知识信号量的基本操作 二、基于环形队列实现生产者消费者模型环形队列单生产单消费模型多生产多消费模型 总结 前言 加油,加油!!! 一、POSIX 信号量 信号量的基础知识 互斥、同步 不只…...

技术视界 | 打造“有脑有身”的机器人:ABC大脑架构深度解析(上)
ABC大脑架构:连接大模型与物理世界的具身智能新范式 在具身智能和类人机器人技术快速发展的背景下,如何高效整合“大模型的认知理解能力”与“对真实物理世界的精准控制”,成为当前智能体系统设计中最具挑战性也是最关键的问题之一。尽管大语…...

使用堡塔和XShell
使用堡塔和XShell 一、SSH协议介绍 SSH为SecureShell的缩写,由IETF的网络小组(NetworkWorkingGroup)所制定;SSH为建立在应用层基础上的安全协议。SSH是较可靠,专为远程登录会话和其他网络服务提供安全性的协议。利用SSH协议可以有效防止远程管理过程中…...

软件项目交付阶段,验收报告记录了什么?有哪些标准要求?
软件项目交付阶段,验收报告扮演着至关重要的角色,它相当于一份详尽的“成绩单”,具体记录了项目完成的具体情况以及是否达到了既定的标准。 项目基本信息 该环节将展示软件项目的核心信息,包括项目名称、开发团队构成、项目实施…...

LightGBM的python实现及参数优化
文章目录 1. LightGBM模型参数介绍2. 核心优势3. python实现LightGBM3.1 基础实现3.1.1 Scikit-learn接口示例3.1.2 Python API示例 3.2 模型调优3.2.1 GridSearchCV简介3.2.2 LightGBM超参调优3.2.3 GridSearchCV寻优结果解读 在之前的文章 Boosting算法【AdaBoost、GBDT 、X…...

封装渐变堆叠柱状图组件附完整代码
组件功能 这是一个渐变堆叠柱状图组件,主要功能包括: 在一根柱子上同时显示高、中、低三种危险级别数据使用渐变色区分不同危险级别(高危红色、中危橙色、低危蓝色)悬停显示详细数据信息(包括总量和各级别数据&#…...
分布式项目保证消息幂等性的常见策略
Hello,大家好,我是灰小猿! 在分布式系统中,由于各个服务之间独立部署,各个服务之间依靠远程调用完成通信,再加上面对用户重复点击时的重复请求等情况,所以如何保证消息消费的幂等性是在分布式或…...

山东大学软件学院创新项目实训开发日志——第十三周
目录 1.开展prompt工程,创建个性化AI助理,能够基于身份实现不同角度和语言风格的回答。 2.对输出进行格式化,生成特定格式的会议计划文档。 3.学习到的新知识 本阶段我所做的工作 1.开展prompt工程,创建个性化AI助理ÿ…...
如何在sublime text中批量为每一行开头或者结尾添加删除指定内容
打开你的文件:首先,在 Sublime Text 中打开你想要编辑的文件,然后全选 行首插入: 选择所有行的开头: 使用快捷键 Ctrl Shift L(Windows/Linux)或 Cmd Shift L(Mac)&…...

Cesium 透明渐变墙 解决方案
闭合路径修复 通过增加额外点确保路径首尾相接 透明渐变效果 使用RGBA颜色模式实现从完全不透明到完全透明的平滑渐变 参数可调性 提供多个可调参数,轻松自定义颜色、高度和圆环尺寸 完整代码实现 <!DOCTYPE html> <html> <head><meta …...
网络原理与 TCP/IP 协议详解
一、网络通信的本质与基础概念 1.1 什么是网络通信? 网络通信的本质是跨设备的数据交换,其核心目标是让不同物理位置的设备能够共享信息。这种交换需要解决三个核心问题: 如何定位设备? → IP地址如何找到具体服务?…...

day022-定时任务-故障案例与发送邮件
文章目录 1. cron定时任务无法识别命令1.1 故障原因1.2 解决方法1.2.1 对命令使用绝对路径1.2.2 在脚本开头定义PATH 2. 发送邮件2.1 安装软件2.2 配置邮件信息2.3 巡检脚本与邮件发送2.3.1 巡检脚本内容2.3.2 制作时任务发送邮件 3. 调取API发送邮件3.1 编写文案脚本3.2 制作定…...

新增 git submodule 子模块
文章目录 1、基本语法2、添加子模块后的操作3、拉取带有submodule的仓库 git submodule add 是 Git 中用于将另一个 Git 仓库作为子模块添加到当前项目中的命令。 子模块允许你将一个 Git 仓库作为另一个 Git 仓库的子目录,同时保持它们各自的提交历史独立。 1、基…...

List优雅分组
一、前言 最近小永哥发现,在开发过程中,经常会遇到需要对list进行分组,就是假如有一个RecordTest对象集合,RecordTest对象都有一个type的属性,需要将这个集合按type属性进行分组,转换为一个以type为key&…...

Linux 使用 Docker 安装 Milvus的两种方式
一、使用 Docker Compose 运行 Milvus (Linux) 安装并启动 Milvus Milvus 在 Milvus 资源库中提供了 Docker Compose 配置文件。要使用 Docker Compose 安装 Milvus,只需运行 wget https://github.com/milvus-io/milvus/releases/download/v2.5.10/milvus-standa…...

AR眼镜+AI视频盒子+视频监控联网平台:消防救援的智能革命
在火灾现场,每一秒都关乎生死。传统消防救援方式面临信息滞后、指挥盲区、环境复杂等挑战。今天,一套融合AR智能眼镜AI视频分析盒子智能监控管理平台的"三位一体"解决方案,正在彻底改变消防救援的作业模式,为消防员装上…...

编程技能:字符串函数10,strchr
专栏导航 本节文章分别属于《Win32 学习笔记》和《MFC 学习笔记》两个专栏,故划分为两个专栏导航。读者可以自行选择前往哪个专栏。 (一)WIn32 专栏导航 上一篇:编程技能:字符串函数09,strncmp 回到目录…...

使用tunasync部署企业内部开源软件镜像站-Centos Stream 9
使用tunasync部署企业内部开源软件镜像站 tunasync 是清华大学 TUNA 镜像源目前使用的镜像方案,本文将介绍如何使用 tunasync 部署企业内部开源软件镜像站。 基于tunasync mirror-web nginx进行镜像站点搭建。 1. tunasync设计 tunasync架构如下: …...
c/c++的opencv像素级操作二值化
图像级操作:使用 C/C 进行二值化 在数字图像处理中,图像级操作 (Image-Level Operations) 是指直接在图像的像素级别上进行处理,以改变图像的视觉特性或提取有用信息。这些操作通常不依赖于图像的全局结构,而是关注每个像素及其邻…...

C++----Vector的模拟实现
上一节讲了string的模拟实现,string的出现时间比vector靠前,所以一些函数给的也比较冗余,而后来的vector、list等在此基础上做了优化。这节讲一讲vector的模拟实现,vector与模板具有联系,而string的底层就是vector的一…...

Mac redis下载和安装
目录 1、官网:https://redis.io/ 2、滑到最底下 3、下载资源 4、安装: 5、输入 sudo make test 进行编译测试 会提示 编辑 6、sudo make install 继续 7、输入 src/redis-server 启动服务器 8、输入 src/redis-cli 启动测试端 1、官网ÿ…...

[25-cv-05718]BSF律所代理潮流品牌KAWS公仔(商标+版权)
潮流品牌KAWS公仔 案件号:25-cv-05718 立案时间:2025年5月21日 原告:KAWS, INC. 代理律所:Boies Schiller Flexner LLP 原告介绍 原告是一家由美国街头艺术家Brian Donnelly创立的公司,成立于2002年2月25日&…...
【PhysUnits】9 取负重载(negation.rs)
一、源码 这段代码是类型级二进制数(包括正数和负数)的取反和取负操作。它使用了类型系统来表示二进制数,并通过特质(trait)和泛型来实现递归操作。 use super::basic::{B0, B1, Z0, N1}; use core::ops::Neg;// 反…...

深度思考、弹性实施,业务流程自动化的实践指南
随着市场环境愈发复杂化,各类型企业的业务步伐为了跟得上市场节奏也逐步变得紧张,似乎只有保持极强的竞争力、削减成本、提升抗压能力才能在市场洪流中博得一席之位。此刻企业需要制定更明智的解决方案,以更快、更准确地优化决策流程。与简单…...

UWB:litepoint获取txquality里面的NRMSE
在使用litepoint测试UWB,获取txquality里面的NRMSE时,网页端可以正常获取NRMSE。但是通过SCPI 命令来获取NRMSE一直出错。 NRMSE数据类型和pyvisa问题: 参考了user guide,发现NRMSE的数值是ARBITRARY_BLOCK FLOAT,非string。 pyvisa无法解析会返回错误。 查询了各种办法…...