react的路由实战使用
环境配置:vite+ts+react18
1、安装包
npm i react-router-dom
2、 根路由配置以及路由挂载
a、在src下面创建router文件夹配置简单的路由信息:
router/index.tsx
import { createBrowserRouter } from "react-router-dom";
import UserLogin from "@/views/login/loginPage";
import HomePage from "@/views/home/homePage";
import React from "react";
const router = createBrowserRouter([{path: "/login",//地址name: "login",//路由名// element: React.createElement(UserLogin),element: <UserLogin />,//要跳转的组件},{path: "/",name: "home",element: <HomePage />,},
]);export default router;
注意:这里有一个坑,我自己踩出来的:
1、如果要以组件的方式构建路由的话就要用tsx后缀命名
2、如果以React.createElement挂路由的话就用ts就可以
3、如果在ts下使用组件方式的路由是无法识别的,会报错哟
b、在实际开发中,一半选择app组件作为路由挂载导出:
app.tsx
import React from "react";
import { RouterProvider } from "react-router-dom";
import router from "./router";
const App: React.FC = () => {return <RouterProvider router={router} />;
};export default App;
c、在main挂载app
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App.tsx";
import "antd/dist/reset.css";
import store from "./store";
import { Provider } from "react-redux";ReactDOM.createRoot(document.getElementById("root")!).render(<React.StrictMode><Provider store={store}><App /></Provider></React.StrictMode>,
);
这样路由就可以使用了。不过现在只是通过手动访问可以了。
3、路由跳转
3.1、useNavigate(高)
- 用途:用于程序化导航,允许你在组件内部触发跳转。
- 示例
import { useNavigate } from 'react-router-dom';function MyComponent() {const navigate = useNavigate();function handleClick() {navigate('/some/path');}return (<button onClick={handleClick}>Go to '/some/path'</button>);
}
3.2、useLocation(高)
- 用途:获取当前路由的位置信息。
- 示例:
-
import { useLocation } from 'react-router-dom';function MyComponent() {const location = useLocation();return (<div><h1>You are at: {location.pathname}</h1></div>); }3.3、useParams(高) - 用途:从当前 URL 中获取动态参数。常用于动态路由
- 示例:
import { useParams } from 'react-router-dom';function UserPage() {const params = useParams();return (<div><h1>User ID: {params.userId}</h1></div>);
}
3.4、useResolvedPath
- 用途:解析一个路径到一个完整的路径对象。
- 示例
import { useResolvedPath } from 'react-router-dom';function Link({ to }) {let resolved = useResolvedPath(to);let href = resolved.pathname + resolved.search;return <a href={href}>{to}</a>;
}
3.5、useMatch:
- 用途:检查一个路径是否与当前 URL 匹配。
- 示例
import { useMatch } from 'react-router-dom';function MyComponent() {const match = useMatch('/users/:userId');if (match) {return <div>User ID: {match.params.userId}</div>;}return null;
}
3.6、useOutlet
- 用途:渲染嵌套路由的子路由内容。
- 示例:
import { useOutlet } from 'react-router-dom';function OutletComponent() {const outlet = useOutlet();return (<div>{outlet}</div>);
}
4、路由详细配置
4.1、配置详情
在 react-router-dom 中,路由配置通常包含以下几个关键的部分:
-
path:- 用途:定义路由的路径模式。
- 示例:
typescript
path: '/users/:userId', - 解释:这里的
path定义了一个路径模式,其中:userId是一个动态参数。
-
element:- 用途:定义当路由匹配时应该渲染的 React 组件。
- 示例:
typescript
element: <UserProfile />, - 解释:当路径匹配时,
<UserProfile />组件将会被渲染。
-
index(可选):- 用途:表示这是一个索引路由,当没有具体路径匹配时渲染。
- 示例:
typescript
index: true, element: <Home />, - 解释:当路径为空或者没有具体的匹配时,
<Home />组件将会被渲染。
-
children(可选):- 用途:定义嵌套路由。
- 示例:
typescript
children: [ { path: 'profile', element: <Profile />, }, ], - 解释:这里的
children定义了一个子路由,当父路由匹配时,子路由也会被考虑。
-
loader(可选):- 用途:加载数据的函数,常用于数据预取。
- 示例:
typescript
loader: () => fetch('/api/data'), - 解释:这个函数会在路由激活前执行,通常用来获取数据。
-
errorElement(可选):- 用途:定义当路由发生错误时渲染的组件。
- 示例:
typescript
errorElement: <Error />, - 解释:当路由加载过程中出现错误时,
<Error />组件会被渲染。
-
caseSensitive(可选):- 用途:定义路径匹配是否区分大小写。
- 示例:
typescript
caseSensitive: true, - 解释:默认情况下路径匹配是不区分大小写的,但可以通过此选项改变这一行为。
4.2、例子
typescript
import { createBrowserRouter, RouterProvider, Route } from "react-router-dom";
import RootLayout from "./layouts/RootLayout";
import Home from "./pages/Home";
import About from "./pages/About";
import Users from "./pages/Users";
import UserProfile from "./pages/UserProfile";// 定义路由对象
const router = createBrowserRouter([{path: "/",element: <RootLayout />,children: [{index: true,element: <Home />,},{path: "about",element: <About />,},{path: "users",element: <Users />,children: [{path: ":userId",element: <UserProfile />,},],},],},
]);// 在 App 组件中使用 RouterProvider 提供路由配置
function App() {return (<RouterProvider router={router} />);
}export default App;
解释:
path: 定义了路由的路径模式。element: 定义了对应的 React 组件。index: 表示这是默认路由。children: 定义了嵌套路由。这些是构建路由的基本组成部分。根据你的应用需求,你可能会使用到更多的特性,例如
loader和errorElement等。
5、路由重定向
5.1、条件重定向
比如用户是否已登录。这种情况下,你可以在路由组件中使用条件逻辑来决定是否重定向。
import { Navigate, createBrowserRouter } from "react-router-dom";
import UserLogin from "@/views/login/loginPage";
import HomePage from "@/views/home/homePage";
import React from "react";
import { getToken } from "../utils/storeages";
const isLogin = getToken("token");
const router = createBrowserRouter([{path: "/login",name: "login",// element: React.createElement(UserLogin),element: <UserLogin />,},{path: "/",name: "home",element: isLogin ? <HomePage /> : <Navigate to="/login" replace />,//条件判断},
]);export default router;
5.2、直接重定向--redirect
推荐使用这一个,方便用于登录认证
import { Navigate, createBrowserRouter, redirect } from "react-router-dom";
import UserLogin from "@/views/login/loginPage";
import ModelPage from "@/views/model";
import HomePage from "@/views/home/homePage";
import DashboardPage from "@/views/Dashboard/DashboardPage";
import React from "react";
import { getToken } from "../utils/storeages";const router = createBrowserRouter([{path: "/login",name: "login",element: <UserLogin />,loader: () => {console.log(getToken("token"));if (getToken("token")) {console.log(1111);return redirect("/home");} else {console.log(2222);return redirect("/login");}},},{path: "/",name: "model",element: <ModelPage />,children: [{path: "/home",name: "home",element: <HomePage />,},{path: "/dashboard",name: "dashboard",element: <DashboardPage />,},{path: "*",element: <Navigate to="/home" />,},],},
]);export default router;
6、动态路由
动态路由其实很简单,简单来说就是一个组件展示不同的数,类似于查看用户信息。每个用户信息不一样,但是组件只有一个。
配置动态路由:
router.tsx
import { Navigate, createBrowserRouter } from "react-router-dom";
import UserLogin from "@/views/login/loginPage";
import HomePage from "@/views/home/homePage";
import React from "react";
import { getToken } from "../utils/storeages";
const isLogin = getToken("token");
console.log(isLogin);
const router = createBrowserRouter([{path: "/login",name: "login",// element: React.createElement(UserLogin),element: <UserLogin />,},{path: "/home/:userId",//动态参数name: "home",// element: isLogin ? <HomePage /> : <Navigate to="/login" replace />,element:<HomePage />,},
]);export default router;
跳转的起点:
import React from "react";
import { useNavigate } from "react-router-dom";
const UserLogin: React.FC = () => {const navigate = useNavigate();function handleClick() {navigate("/home/1");}return (<div ><button onClick={handleClick}>Go to User 1</button></div>);
};export default UserLogin;
跳转的目标:
import React from "react";
import { useParams } from "react-router-dom";
const HomePage: React.FC = () => {const {userId} = useParams()console.log(userId);return <div>homePage{userId}</div>;
};export default HomePage;
这样就实现了一个组件多用的情况,其实就是展示不同的信息
7、嵌套路由(子路由)
配置嵌套路由:
import { Navigate, createBrowserRouter } from "react-router-dom";
import UserLogin from "@/views/login/loginPage";
import HomePage from "@/views/home/homePage";
import HaderPage from '@/views/home/header/header'
import React from "react";
const router = createBrowserRouter([{path: "/login",name: "login",element: <UserLogin />,},{path: "/home",name: "home",element:<HomePage />,children: [{path: "/home/header",name: "header",element: <HaderPage />,},],},
]);export default router;
配置home组件:
import React from "react";
import { useParams,useNavigate,Outlet } from "react-router-dom";
const HomePage: React.FC = () => {const {userId} = useParams()const navigate = useNavigate()console.log(userId);const headerButon = () => {console.log(111);navigate("/home/header")};return (<div><div>homePage{userId}</div><button onClick={() => {headerButon()}}>展示header</button><Outlet/></div>);
};export default HomePage;
展示的子组件:
import React from "react";
const HeaderPage: React.FC = () => {return <div>HeaderPage</div>;
};export default HeaderPage;
具体操作:
1、首先在router配置好子组件
2、创建子组件
3、在home组件添加路由跳转到/home/header子组件,并且用 <Outlet/>展示子组件的位子
注意:
1、必须要有 <Outlet/>,不然子组件不会展示
8、默认路由
在实际开发中在未操作的情况下会默认展示一个页面,这个页面我们成为默认路由页面
import { Navigate, createBrowserRouter } from "react-router-dom";
import UserLogin from "@/views/login/loginPage";
import ModelPage from "@/views/model";
import HomePage from "@/views/home/homePage";
import DashboardPage from "@/views/Dashboard/DashboardPage";
import React from "react";const router = createBrowserRouter([{path: "/login",name: "login",element: <UserLogin />,},{path: "/",name: "model",element: <ModelPage />,children: [{path: "/home",name: "home",element: <HomePage />,},{path: "/dashboard",name: "dashboard",element: <DashboardPage />,},{path: "*",//默认路由指向的页面element: <Navigate to="/home" />,},],},
]);export default router;
9、路由守卫
方法 1: 使用 useEffect 和 useHistory / useNavigate
这里其实没什么变化,主要是加了一个loader下面的redirect重定向路由
router.tsx
import { Navigate, createBrowserRouter,redirect } from "react-router-dom";
import UserLogin from "@/views/login/loginPage";
import HomePage from "@/views/home/homePage";
import DashboardPage from "@/views/dashboard/dashboardPage";
import React from "react";
import { LayoutGuard } from "./utils/guard";
import { getToken } from "@/utils/storeages";const router = createBrowserRouter([{path: "/login",name: "login",element: <UserLogin />,loader: () => {const token = getToken('token');if (token) {return redirect('/home');}return null;},},{path: "/",name: "model",// element: <ModelPage />,element: <LayoutGuard />,children: [{path: "/home",name: "home",element: <HomePage />,},{path: "/dashboard",name: "dashboard",element: <DashboardPage />,},{path: "*",element: <Navigate to="/home" />,},],},
]);export default router;
router/authGuard.tsx
守卫操作:
import React, { useEffect } from 'react';
import { useNavigate } from 'react-router-dom';
import { getToken } from '@/utils/storeages';function AuthGuard({ children }: { children: JSX.Element }) {const navigate = useNavigate();useEffect(() => {const token = getToken('token');console.log('token', token);if (token) {// 如果已经登录,则重定向到登录页面navigate('/home');} else {navigate('/login');}}, [navigate]);return <>{children}</>;
}export default AuthGuard;
封装路由组件中导入的 <LayoutGuard />,
import AuthGuard from "./AuthGuard";
import ModelPage from "@/views/model";
import React from "react";export const LayoutGuard = () => {return (<AuthGuard><ModelPage /></AuthGuard>);
};
方法 2: 使用自定义高阶组件 (HOC)
这种方法可以让你更灵活地控制路由组件的行为,特别是在需要复用相同逻辑的情况下。
import React from 'react';
import { useNavigate } from "react-router-dom";function withAuth(WrappedComponent) {return function AuthenticatedComponent(props) {const navigate = useNavigate();const isLoggedIn = false; // 假设这是从你的应用状态中获取的值if (!isLoggedIn) {// 如果用户未登录,则重定向到登录页面navigate('/login');return null;}return <WrappedComponent {...props} />;};
}function ProtectedPage() {return (<div><h1>Welcome to the protected area!</h1></div>);
}const AuthenticatedProtectedPage = withAuth(ProtectedPage);function App() {return (<div><AuthenticatedProtectedPage /></div>);
}export default App;
方法 3: 使用 Route 的 element 属性
在 React Router v6 中,你可以直接在 Route 的 element 属性中定义一个组件,该组件负责路由守卫的逻辑。
import React from 'react';
import { createBrowserRouter, RouterProvider, Route, Link, useNavigate } from "react-router-dom";function ProtectedPage() {const isLoggedIn = false; // 假设这是从你的应用状态中获取的值const navigate = useNavigate();if (!isLoggedIn) {// 如果用户未登录,则重定向到登录页面navigate('/login');return null;}return (<div><h1>Welcome to the protected area!</h1></div>);
}function App() {return (<div><Route path="/protected" element={<ProtectedPage />} /></div>);
}const router = createBrowserRouter([{path: '/',element: <App />,children: [{path: '/protected',element: <ProtectedPage />,},],},
]);function Root() {return (<RouterProvider router={router} />);
}export default Root;
方法 4: 使用 useLocation 和条件渲染
这种方法适用于需要在组件内部根据当前 URL 执行某些逻辑的情况。
import React, { useEffect } from 'react';
import { useNavigate, useLocation } from "react-router-dom";function ProtectedRoute({ children }) {const navigate = useNavigate();const location = useLocation();const isLoggedIn = false; // 假设这是从你的应用状态中获取的值useEffect(() => {if (!isLoggedIn && location.pathname === '/protected') {// 如果用户未登录并且试图访问受保护的页面,则重定向到登录页面navigate('/login');}}, [isLoggedIn, navigate, location]);return isLoggedIn ? children : null;
}function App() {return (<div><ProtectedRoute><h1>Welcome to the protected area!</h1></ProtectedRoute></div>);
}export default App;
总结
-
使用
useEffect和useHistory/useNavigate:- 适用于简单的场景,可以在组件加载时检查条件并进行重定向。
-
使用自定义高阶组件 (HOC):
- 更适合需要复用相同逻辑的情况,可以方便地应用于多个组件。
-
使用
Route的element属性:- 直接在
Route的element属性中定义一个组件,该组件负责路由守卫的逻辑。
- 直接在
-
使用
useLocation和条件渲染:- 适用于需要根据当前 URL 执行某些逻辑的情况。
选择哪种方法取决于你的具体需求和应用场景。
相关文章:
react的路由实战使用
环境配置:vitetsreact18 1、安装包 npm i react-router-dom 2、 根路由配置以及路由挂载 a、在src下面创建router文件夹配置简单的路由信息: router/index.tsx import { createBrowserRouter } from "react-router-dom"; import UserLogin…...
python 字典转成类 构建类
目录 python 字典转成类 复杂嵌套示例: 动态实例化类 太好用了! python 字典转成类 class DictToClass:def __init__(self, dictionary):for key, value in dictionary.items():if isinstance(value, dict):# 如果值是字典,递归转换为类的实例setattr(self, key, DictToC…...
springboot 过滤器
1、过滤器的实现 springboot中过滤器通过实现接口Filter并重写init、doFilter、destroy三个方法。在三个方法中加入自己的业务逻辑处理。 【注意】Filter接口的完整包名在不同的jdk版中中的变化。这里示例中使用的版本为 open-jdk17。完整名称 jakarta.servlet.Filter。如果使…...
【C语言篇】深入理解指针1
文章目录 内存和地址内存编址 指针变量和地址取地址操作符指针变量和解引用操作符指针变量指针变量类型解引用操作符指针变量的大小 指针变量类型的意义指针的解引用指针-整数void*指针 const修饰指针指针运算指针-整数指针-指针指针的关系运算 野指针野指针成因如何规避野指针…...
IAP程序升级 与 电脑BIOS 的关系
IAP (In-Application Programming) 程序升级 IAP程序升级是一种技术,允许设备在运行过程中更新其自身的固件或软件,而不需要外部工具或设备的介入。这种技术特别适用于嵌入式系统和物联网(IoT)设备。其主要由三部分构成࿰…...
Java使用MQTT协议
MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议)是一种轻量级的、基于发布/订阅模式的物联网通信协议。它构建于TCP/IP协议之上,由IBM在1999年发布。MQTT的主要特点包括: 轻量级与高效:M…...
等级+时间的优先级算法
简介 本算法为等级与时间结合计算对应优先级逻辑 等级越高者优先级越高 同等级下,时间越小者优先级越高 实现 主方法 calculatePriority import com.zk.blog.enums.TypeEnum; import org.apache.commons.lang3.StringUtils;/*** program: * description:* autho…...
物流仓库安全视频智能管理方案:构建全方位、高效能的防护体系
一、背景分析 随着物流行业的快速发展和仓储需求的日益增长,仓库安全成为企业运营中不可忽视的重要环节。传统的人工监控方式不仅效率低下,且难以做到全天候、无死角覆盖,给仓库资产和人员安全带来潜在风险。因此,引入仓库安全视…...
jackson反序列化漏洞
jackson反序列化漏洞 反序列化漏洞触发根因jackson介绍jackson反序列化漏洞关键点enableDefaultTypingactivateDefaultTypingJsonTypeInfo 漏洞触发场景漏洞复现环境引入依赖pocactivateDefaultTypingenableDefaultTypingJsonTypeInfo 参考 很久没写blog,最近慢慢开…...
Java | Leetcode Java题解之第328题奇偶链表
题目: 题解: class Solution {public ListNode oddEvenList(ListNode head) {if (head null) {return head;}ListNode evenHead head.next;ListNode odd head, even evenHead;while (even ! null && even.next ! null) {odd.next even.nex…...
100 Exercises To Learn Rust 挑战!准备篇
公司内部的学习会非常活跃!我也参与了Rust学习会,并且一直在研究rustlings。最近,我发现了一个类似于rustlings的新教程网站:Welcome - 100 Exercises To Learn Rust。 rustlings是基于Rust的权威官方文档《The Rust Programming…...
瑞_RabbitMQ_初识MQ
文章目录 1 初识MQ1.1 同步调用1.1.1 同步调用的优势1.1.2 同步调用的缺点 1.2 异步调用1.2.1 异步调用的角色1.2.2 异步调用的优势1.2.3 异步调用的缺点1.2.4 异步调用的场景 1.3 MQ技术选型 2 RabbitMQ2.1 安装2.1.1 资源准备2.1.2 安装步骤 2.2 RabbitMQ架构2.3 RabbitMQ管理…...
系统内存管理:虚拟内存、内存分段与分页、页表缓存TLB以及Linux内存管理
虚拟内存 虚拟内存是一种操作系统提供的机制,用于将每个进程分配的独立的虚拟地址空间映射到实际的物理内存地址空间上。通过使用虚拟内存,操作系统可以有效地解决多个应用程序直接操作物理内存可能引发的冲突问题。 在使用虚拟内存的情况下࿰…...
Java每日一练_模拟面试题5(堆和栈的区别)
在Java中,堆(Heap)和栈(Stack)是两个不同的内存区域,它们在存储内容、管理方式、空间大小、分配方式等多个方面存在显著的区别。以下是Java中堆和栈的主要区别: 1. 存储内容不同 堆࿱…...
传感器校正和测试
是 一。舵机在使用过程中为了防止手动扭动损坏其中的齿轮,一般会使用代码测试并校正到0位。 #include <Servo.h> Servo myservo; // 创建一个Servo对象 // 连接到舵机信号线的Arduino引脚 int servoPin 9; void setup() { myservo.attach(servoPin…...
Eclipse 悬浮提示:提高编程效率的利器
Eclipse 悬浮提示:提高编程效率的利器 引言 在当今的软件开发领域,Eclipse 是一款广受欢迎的集成开发环境(IDE)。它以其强大的功能和灵活性而著称,被全球的开发者用于各种编程语言和项目。Eclipse 的一个显著特点是其…...
Vault系列之:创建令牌
Vault系列之:创建令牌 一、Vault令牌二、令牌认证三、创建一个新的令牌四、使用令牌登陆五、 撤销令牌 一、Vault令牌 Vault令牌是Vault服务器提供的一种身份验证方式,用于授权和访问Vault中存储的资源。Vault令牌可以是客户端令牌或服务令牌。客户端令…...
如何在 Windows 10 环境下安装和配置 MySQL:初学者指南
如何在 Windows 10 环境下安装和配置 MySQL:初学者指南 MySQL 是一个流行的开源数据库管理系统,广泛应用于各种应用程序中。对于初学者来说,了解如何在 Windows 10 环境下安装和配置 MySQL 是一个重要的第一步。本篇博客将详细介绍如何完成这…...
Ubuntu 24.04上报:Error: could not connect to ollama app, is it running?的解决方法
说起来这个问题真实让人无语。按照我之前说过的方法:设置Ollama在局域网中访问的方法(Ubuntu)_ollama 局域网访问-CSDN博客 把Ollama的默认端口修改后,如果再运行: ollama ps 则会报下面的错: Error: c…...
字典树查重(到底要开多大的空间啊)
前言:烦死了,这个题目一看就是用字典树来做,但是空间不知道开多大,烦死了 后来发现其实tree的第一维空间直接开极端的情况就行,就好像这一题,最多有 1e4 个字符串,每个字符串最长为 50ÿ…...
DOL-CHS-MODS:一站式游戏体验优化整合方案
DOL-CHS-MODS:一站式游戏体验优化整合方案 【免费下载链接】DOL-CHS-MODS Degrees of Lewdity 整合 项目地址: https://gitcode.com/gh_mirrors/do/DOL-CHS-MODS 方案价值:为何选择整合方案 DOL-CHS-MODS 提供了一种智能化的游戏资源整合解决方案…...
Windows DLL注入终极指南:Xenos工具完全解析
Windows DLL注入终极指南:Xenos工具完全解析 【免费下载链接】Xenos Windows dll injector 项目地址: https://gitcode.com/gh_mirrors/xe/Xenos 你是否曾需要向Windows进程注入DLL文件,但发现传统方法复杂且不稳定?Xenos正是为解决这…...
YEDDA中文文本标注工具:零基础快速上手的高效标注解决方案
YEDDA中文文本标注工具:零基础快速上手的高效标注解决方案 【免费下载链接】yedda-py3 项目地址: https://gitcode.com/gh_mirrors/ye/yedda-py3 在人工智能和自然语言处理领域,数据标注是构建高质量模型的基础。YEDDA中文文本标注工具是一款专为…...
Phi-4-mini-reasoning企业知识库接入:PDF解析+向量化+推理问答闭环
Phi-4-mini-reasoning企业知识库接入:PDF解析向量化推理问答闭环 1. 模型简介与部署验证 Phi-4-mini-reasoning 是一个基于合成数据构建的轻量级开源模型,专注于高质量、密集推理的数据处理能力。作为Phi-4模型家族成员,它特别强化了数学推…...
DeepSeek-OCR-2保姆级部署教程:5分钟在星图GPU平台一键搭建OCR服务
DeepSeek-OCR-2保姆级部署教程:5分钟在星图GPU平台一键搭建OCR服务 1. 为什么你需要这个OCR服务 如果你经常需要处理扫描文档、发票、合同或者各种纸质材料的数字化,肯定遇到过传统OCR工具的痛点——表格识别混乱、多栏文本顺序错乱、公式识别一塌糊涂…...
cv_unet_image-colorization部署案例:RTX显卡5分钟搭建AI上色工作站
cv_unet_image-colorization部署案例:RTX显卡5分钟搭建AI上色工作站 1. 项目简介 你是否遇到过这样的情况:翻看老照片时,发现很多珍贵的黑白照片已经褪色发黄,想要恢复色彩却不知道从何下手?或者作为摄影师ÿ…...
学历作为硬实力:当代中国权力结构中知识资本的制度化逻辑与社会地位再生产机制
学历作为硬实力:当代中国权力结构中知识资本的制度化逻辑与社会地位再生产机制 作者:培风图南以星河揽胜 专栏链接:澄心观道 字数:约 14,200 字 | 阅读时长:约 52 分钟 引言:一个被广泛观察却少有深究的社会…...
如何用UAV-Flow实现语音控制无人机?手把手教你搭建环境与避坑指南
如何用UAV-Flow实现语音控制无人机?从环境搭建到实战避坑全指南 当无人机遇上自然语言处理,会擦出怎样的火花?去年接触UAV-Flow时,我正为一个农业巡检项目头疼——传统摇杆控制需要专业飞手,而农户们更习惯说"绕着…...
KT0803K FM发射芯片Arduino驱动开发与射频工程实践
1. KT0803系列FM发射芯片Arduino库深度解析与工程实践指南1.1 芯片定位与系统级约束KT0803及其衍生型号(KT0803K/L/M)是高度集成的单芯片FM广播发射器,专为低功耗、小体积音频广播应用设计。该系列芯片内部集成了PLL频率合成器、立体声编码器…...
Windows 11下Keil5 MDK与C51共存安装全攻略(附ST-Link驱动避坑指南)
Windows 11下Keil5 MDK与C51共存安装全攻略(附ST-Link驱动避坑指南) 在嵌入式开发领域,Keil作为经典开发工具链,其MDK(Microcontroller Development Kit)和C51版本分别服务于ARM架构和8051架构单片机开发。…...
