【React】基础版React + Redux实现教程,自定义redux库,Redux Toolkit教程
本项目是一个在react中,使用 redux 管理状态的基础版实现教程,用简单的案例练习redux的使用,旨在帮助学习 redux 的状态管理机制,包括 store
、action
、reducer
、dispatch
等核心概念。
项目地址:https://github.com/YvetW/redux-mini-demo
注:项目中包含多个版本的代码,有助于理解redux,运行前请先选择需要的版本,修改目录名为src。
版本:
- React v19
- Redux v5
- React-Redux v9
- TypeScript
- Vite
1. 初始化项目
使用 Vite
创建 React+TypeScript 项目:
npm create vite@latest my-app -- --template react-ts
cd my-app
npm install
主要目录结构
my-app/
├── src/
│ ├── redux/
│ │ ├── action-types.ts # 定义 Action Types
│ │ ├── actions.ts # 定义 Actions
│ │ ├── reducers.ts # 定义 Reducers
│ │ ├── store.ts # 创建 Store
│ ├── App.tsx # 组件主入口
│ ├── main.tsx # 入口文件,渲染 App
│ ├── index.css # 样式文件
├── package.json # 依赖管理
├── tsconfig.json # TypeScript 配置
└── vite.config.ts # Vite 配置
2. 在 React 组件中使用 Redux
本版本不使用 react-redux
或 @reduxjs/toolkit
,而是直接使用 Redux 的原生 createStore
API(已过时,但有助于理解 Redux 的核心概念)。
2.1 创建 Action Types (action-types.ts
)
- 在 Redux 中,所有的
action
都应有一个唯一的type
,定义type
常量。 - 例如:
INCREMENT
、DECREMENT
、ADD_MESSAGE
。
export const INCREMENT = 'increment'
export const DECREMENT = 'decrement'
export const ADD_MESSAGE = 'add_message'
2.2 创建 Reducers (reducers.ts
)
- Redux 需要使用
reducers
函数处理state
变化。 - 创建两个
reducer
:count
和messages
。 - 根据不同
action
类型更新state
,返回新的state
。
import {combineReducers} from 'redux';
import {ADD_MESSAGE, DECREMENT, INCREMENT} from './action-types.ts';
import {Action} from './actions.ts';// 管理count
const initCount: number = 0;function count(state: number = initCount, action: Action): number {console.log('count', state, action);switch (action.type) {case INCREMENT:return state + action.data;case DECREMENT:return state - action.data;default:return state;}
}// 管理messages
const initMessages: string[] = [];function messages(state: string[] = initMessages, action: Action): string[] {console.log('messages', state, action);switch (action.type) {case ADD_MESSAGE:return [action.data, ...state]default:return state;}
}export default combineReducers({count, messages});// 整体state状态结构: {count: 2, messages: ['xx', 'xxx']}
2.3 创建 Actions (actions.ts
)
- Actions 是 Redux store 唯一的数据来源。
- 创建
increment
、decrement
和addMessage
action。
import {INCREMENT, DECREMENT, ADD_MESSAGE} from './action-types.ts';// 定义 CountAction 的类型
interface CountAction {type: typeof INCREMENT | typeof DECREMENT;data: number;
}// 定义 MessageAction 的类型
interface MessageAction {type: typeof ADD_MESSAGE; // 只有 ADD_MESSAGE 类型data: string; // data 是一个字符串
}// 联合类型
export type Action = CountAction | MessageAction;export const increment = (number: number): CountAction => ({type: INCREMENT, data: number});export const decrement = (number: number): CountAction => ({type: DECREMENT, data: number});export const add_message = (message: string): MessageAction => ({type: ADD_MESSAGE, data: message});
2.4 创建 Store (store.ts
)
- 通过
createStore(rootReducer)
创建 Reduxstore
,集中管理应用状态。
import { createStore } from 'redux';
import reducers from './reducers'; // 包含多个reducer的reducerexport default createStore(reducers)
2.5 在 App.tsx
中使用 store
- 通过
props.store.getState()
获取state
,控制组件渲染。 - 通过
props.store.dispatch(action)
触发状态更新。
import {useState} from 'react';
import {Store} from 'redux';
import {Action, increment, decrement, add_message} from './redux/actions.ts';// 为 App 组件定义一个 Props 类型,这个类型包含 store
interface AppProps {store: Store<{count: number;messages: string[];}, Action>;
}function App({store}: AppProps) {const [selectedValue, setSelectedValue] = useState<number>(1);const [message, setMessage] = useState<string>('');const count = store.getState().count;const messages = store.getState().messages;function handleIncrement() {store.dispatch(increment(selectedValue));}function handleDecrement() {store.dispatch(decrement(selectedValue));}// 奇数增加function handleIncrementIfOdd() {// setCount 是异步的,如果 Redux 状态更新了,count 可能不会立即反映出来,直接从 store.getState() 读取最新的 countif (store.getState().count % 2 === 1) {store.dispatch(increment(selectedValue));}}// 异步增加function handleIncrementIfAsync() {setTimeout(() => {store.dispatch(increment(selectedValue));}, 1000);}function handleAdd() {if (message.trim()) {store.dispatch(add_message(message));setMessage('');}}return (<div className="App"><div className="count">click <span>{count}</span> times</div><selectid="number" value={selectedValue}// <option> 的 value 默认是字符串类型(即使它是一个数字),这里强制转换为数字onChange={event => setSelectedValue(Number(event.target.value))}>{[1, 2, 3, 4, 5].map((item) => (<option value={item} key={item}>{item}</option>))}</select><button onClick={handleIncrement}>+</button><button onClick={handleDecrement}>-</button><button onClick={handleIncrementIfOdd}>increment if odd</button><button onClick={handleIncrementIfAsync}>increment async</button><hr /><inputtype="text"value={message}onChange={event => setMessage(event.target.value)}/><button onClick={handleAdd}>add text</button><ul>{messages.map((msg, index) => (<li key={index}>{msg}</li>))}</ul></div>);
}export default App;
2.6 在 main.tsx
中订阅 Store 并触发渲染
createRoot()
挂载App
组件。- 通过
store.subscribe()
监听state
变化,每次dispatch
触发state
变更时重新渲染App
。 - React 18 及以上使用
createRoot()
进行渲染,注意避免重复createRoot()
调用。
import {StrictMode} from 'react';
import {createRoot} from 'react-dom/client';
import './index.scss';
import App from './App';
import store from './redux/store.ts';const root = createRoot(document.getElementById('root')!); // 只调用一次 createRoot()// root.render() 负责后续更新
function render() {root.render(<StrictMode><App store={store} /></StrictMode>,);
}// 初次渲染
render();// 订阅 store,state 变化时触发 render
store.subscribe(render);
3. 自定义 redux 库
自己定义一个简易的 redux 库,主要针对 createStore 和 combineReducers 的核心概念,帮助理解redux的原理。
简单来说,createStore
用来创建存储和管理应用状态的对象,而 combineReducers
用来将多个子 reducer 合并成一个单一的 reducer。
注:完整版请看项目代码。
3.1 createStore
- 作用:用于创建一个 Redux Store,负责管理应用的状态。
- 接收的参数:
reducer
:根 reducer,决定如何根据action
更新state
。- 可选的
preloadedState
:初始化时的状态。
- 返回的
store
对象包含:dispatch
:分发action,会触发reducer调用,返回一个新的state,调用所有绑定的listenergetState
:得到内部管理的state对象subscribe
:监听state
的变化,并在状态变化时触发回调。
export function createStore<S, A extends Action>(rootReducer: Reducer<S, A>): Store<S> {// 内部state,第一次调用reducer得到初始状态并保存let state: S;// 内部保存n个listener的数组const listeners: (() => void)[] = [];// 初始调用reducer得到初始state值state = rootReducer(undefined, {type: '@mini-redux'} as A);// 得到内部管理的state对象function getState() {return state;}// 分发action,会触发reducer调用,返回一个新的state,调用所有绑定的listenerfunction dispatch(action: Action) {// 调用reducer,得到一个新的state,保存state = rootReducer(state, action as A);// 调用listeners中所有的监视回调函数listeners.forEach(listener => listener());}// 订阅state变化,产生新的状态,也就是dispatch时才执行function subscribe(listener: () => void) {listeners.push(listener); // 将listener加入到订阅列表// 返回一个取消订阅的函数(main.ts 通常不需要手动取消,只执行一次,store.subscribe(render) 只执行一次,不会不断创建新的 listener,所以 不会造成内存泄漏。)return () => {const index = listeners.indexOf(listener);if (index >= 0) {listeners.splice(index, 1);}};}// 返回一个store对象return {getState, dispatch, subscribe};
}
3.2 combineReducers
- 作用:将多个子 reducer 组合成一个根 reducer。
- 接收的参数:
reducers
:一个对象,其中包含多个子 reducer,每个子 reducer 负责管理state
的一部分。
- 这个函数返回一个新的 reducer,能够根据
action
调用每个子 reducer,更新对应的state
部分。
// 接收一个包含多个reducer函数的对象,返回一个新的reducer函数
export function combineReducers<S, A extends Action>(reducers: { [K in keyof S]: Reducer<S[K], A> }
) {return function (state: Partial<S> = {} as S, action: A): S { // 这个 rootReducer 函数会传给 createStore()return Object.keys(reducers).reduce((newState, key) => {// 确保类型安全:key 是 S 类型的有效键newState[key as keyof S] = reducers[key as keyof S](state[key as keyof S], action)return newState}, {} as S)};
}
4. react-redux
react-redux
是一个官方推荐的 React 库,它将 Redux 状态管理与 React 组件结合起来,帮助你更方便地在 React 应用中使用 Redux。
4.1 Provider
Provider
是一个 React 组件,它的作用是将 Redux store 传递给整个应用。它让组件树中的所有组件都能访问到 Redux store,因此,Provider
通常包裹在应用的最外层。
const root = createRoot(document.getElementById('root')!);root.render(<StrictMode><Provider store={store}><App /></Provider></StrictMode>
);
store
是你通过createStore
创建的 Redux store。Provider
会将 Redux store 传递给组件树中的所有组件。
4.2 useSelector
和 useDispatch
Hook
在旧版 react-redux 中,使用 connect()
高阶组件(HOC)将 Redux 状态和 dispatch 方法注入到组件中。
在 React-Redux v7.1 及以上版本中,使用 React Hooks 来代替 connect
,使函数组件可以直接访问 Redux 状态和 dispatch 方法,使得代码更加简洁:
useSelector
:让你从 Redux store 中获取状态数据。useDispatch
:让你获取dispatch
方法并用于派发action
。
示例:
const count = useSelector((state: RootState) => state.count);const messages = useSelector((state: RootState) => state.messages);const dispatch = useDispatch<AppDispatch>();function handleIncrement() {dispatch(increment(selectedValue));}
5. redux-toolkit
将前面的redux版本更新为redux-toolkit版本。
5.1 安装 Redux Toolkit
npm install @reduxjs/toolkit
5.2 替换 createStore
为 configureStore
import { configureStore } from '@reduxjs/toolkit';
import counterReducer from './counterSlice';
import messagesReducer from './messagesSlice';const store = configureStore({reducer: {counter: counterReducer,messages: messagesReducer}
});export default store;
export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;
configureStore
自动启用 Redux DevTools,不需要额外配置。reducer
现在是一个对象,每个状态片段(slice)有自己的 reducer。
5.3 使用 createSlice
替换 reducers
在 Redux Toolkit(RTK)中,通常会在 redux 目录下创建一个 slices 目录(或 features 目录)来存放 slice 文件,如下所示:
/src├── /redux│ ├── /slices│ │ ├── counterSlice.ts│ │ ├── messagesSlice.ts│ ├── store.ts│ ├── hooks.ts
import { createSlice, PayloadAction } from '@reduxjs/toolkit';const initialState = { value: 0 };const counterSlice = createSlice({name: 'counter',initialState,reducers: {increment: (state, action: PayloadAction<number>) => {state.value += action.payload;},decrement: (state, action: PayloadAction<number>) => {state.value -= action.payload;}}
});export const { increment, decrement } = counterSlice.actions;
export default counterSlice.reducer;
createSlice
自动生成action
和reducer
,不再需要手写switch-case
逻辑。- 直接修改
state
,RTK 内部使用Immer
处理不可变性。 PayloadAction<number>
取代Action
里的data
。
5.4 替换 actions.ts
RTK 版不需要手写 actions,可以直接从 slice
里导出:
import { increment, decrement } from './counterSlice';// 直接在组件中 dispatch
dispatch(increment(1));
5.5 useSelector
和 useDispatch
import { useSelector, useDispatch } from 'react-redux';
import { RootState, AppDispatch } from '../redux/store';
import { increment, decrement } from '../redux/counterSlice';const dispatch = useDispatch<AppDispatch>(); // 需要类型标注
const count = useSelector((state: RootState) => state.counter.value);
dispatch(increment(1));
useDispatch<AppDispatch>()
让dispatch
知道Redux Toolkit
的thunk
类型。
5.6 处理异步逻辑
以前 Redux 需要 redux-thunk
:
export const incrementAsync = (amount: number) => {return (dispatch: Dispatch<Action>) => {setTimeout(() => {dispatch(increment(amount));}, 1000);};
};
RTK 版使用 createAsyncThunk
:
import { createAsyncThunk } from '@reduxjs/toolkit';export const incrementAsync = createAsyncThunk('counter/incrementAsync', // action typeasync (value: number) => {// 模拟异步操作return new Promise<number>((resolve) => {setTimeout(() => {resolve(value);}, 1000);});}
);
在 slice
里处理异步:
import { createSlice } from '@reduxjs/toolkit';
import { incrementAsync } from './counterThunk';const counterSlice = createSlice({name: 'counter',initialState: { count: 0 },reducers: {increment: (state, action) => { state.count += action.payload; },decrement: (state, action) => { state.count -= action.payload; }},extraReducers: (builder) => {builder.addCase(incrementAsync.pending, (state) => {// 在异步请求开始时可以做一些状态管理// 比如:可以设置 loading 状态}).addCase(incrementAsync.fulfilled, (state, action) => {state.count += action.payload;}).addCase(incrementAsync.rejected, (state, action) => {// 可以在这里处理错误});},
});export const { increment, decrement } = counterSlice.actions;
export default counterSlice.reducer;
在组件中你需要使用 dispatch 来派发 incrementAsync 而不是 increment:
// 直接派发异步增加function handleIncrementIfAsync() {dispatch(incrementAsync(selectedValue));}
5.7 迁移 combineReducers
以前 Redux 需要 combineReducers
,RTK 版直接传 reducer
对象,configureStore
自动调用 combineReducers
,不需要手写。
import { configureStore } from '@reduxjs/toolkit';
import counterReducer from './counterSlice';
import messagesReducer from './messagesSlice';const store = configureStore({reducer: {counter: counterReducer,messages: messagesReducer}
});export default store;
总结
- 用
configureStore
代替createStore
,自动组合 reducers。 - 用
createSlice
代替reducers.ts
,不需要switch-case
。 - 不需要手写
actions.ts
,直接用slice.actions
。 - 异步逻辑用
createAsyncThunk
代替redux-thunk
。 - 自动启用 Redux DevTools 和
immer
,代码更简洁。
码字不易,欢迎点赞收藏关注!感恩比心~
相关文章:
【React】基础版React + Redux实现教程,自定义redux库,Redux Toolkit教程
本项目是一个在react中,使用 redux 管理状态的基础版实现教程,用简单的案例练习redux的使用,旨在帮助学习 redux 的状态管理机制,包括 store、action、reducer、dispatch 等核心概念。 项目地址:https://github.com/Yv…...
onlyoffice实现office文件在线编辑保存
一、简介 onlyoffice是开源的在线文档编辑软件,支持主流的office格式,可实现文档在线编辑保存,多人协作编辑等场景,是目前我用过的功能最完善且强大的在线office编辑软件; 二、安装onlyoffice 这里仅介绍docker安装 简单运行查看sudo docker run -i -t -d -p 80:80 --…...
Transformer革命:人工智能如何突破语言理解的边界
Transformer革命:人工智能如何突破语言理解的边界? 当你在手机输入法中打出"苹果"时,系统是否知道你要输入水果还是手机品牌?这个看似简单的选择,背后隐藏着自然语言处理领域二十年来最深刻的变革。2017年谷…...
禅道品牌全面战略升级:开创项目管理国产化替代新格局
2025年,禅道软件完成企业品牌战略深度升级。此次升级,从产品力、服务力到生态圈构建等方面进行了全面优化,以更智慧的解决方案、更开放的生态布局,更安全的国产化解决方案,助力企业实现从“工具应用”到“价值创造”的…...
软件项目管理课程之第4讲:软件需求管理
讲授内容 项目案例 软件需求管理的基本概念 软件需求开发 软件需求管理 项目案例 案例背景:小王作为软件项目负责人,带领团队开展需求调查工作,但在需求分析和后续开发过程中出现了一系列问题。 问题表现: 项目规模庞大&…...
java基础知识和语法
1.类的信息加载完成后,会自动调用静态代码块,可以完成静态属性的初始化功能 对象准备创建时,也会自动调用代码块,但不是静态的; public class java_3_24 {public static void main(String[] args) {new User08();}} …...
横扫SQL面试——事件流处理(峰值统计)问题
横扫SQL面试 📌 事件流处理(峰值统计)问题 “会议室预定冲突怎么查? 🔍 服务器瞬时负载如何算?🎢 健身房的‘人挤人’高峰究竟出现在几点?🏃♂️” 这些看似毫不相干…...
如何降低频谱分析仪的底噪
测量微小信号的时候,底噪可能会淹没有用的信号:(如下图,底噪为-60dB) 如何降低底噪: 1.分辨率带宽RBW设置小一点,可以减小信号的底噪 2.减小衰减器(频谱分析仪底噪的功率随着输入衰…...
C语言基础知识09---文件操作
目录 文件操作 1.1 文件操作 1.2 文件操作的数据传输形式 1.3 文件操作的分类 1.4 文件存储格式 1.5 文件流指针 1.6 函数名:fopen() 1.7 函数名:fclose() 1.8 函数名:fprintf() 1.9 函数名:fscanf() 1.10 函数名&…...
GRS认证的主要步骤是什么?
GRS认证的具体步骤,是一个严谨而系统的过程,旨在确保产品从原料来源到最终消费的每一个环节都符合全球回收标准(Global Recycle Standard,简称GRS)的严格要求。 首先,企业需要向GRS认证机构提交申请&#…...
探究 CSS 如何在HTML中工作
2025/3/28 向全栈工程师迈进! 一、CSS的作用 简单一句话——美化网页 <p>Lets use:<span>Cascading</span><span>Style</span><span>Sheets</span> </p> 对于如上代码来说,其显示效果如下࿱…...
软件工程面试题(七)
1、DAO设计模式及DELEGATE模式 DAO(Data Access Object)模式实际上是两个模式的组合,即Data Accessor 模式和 Active Domain Object 模式,其中 Data Accessor 模式实现了数据访问和业务逻辑的分离,而Active Domain Object 模式实现了业务数据的对象化封装,一般我们将这两…...
AfxMessageBox()如何显示string字符串
书籍:《Visual C 2017从入门到精通》的2.7 字符串 环境:visual studio 2022 内容:几个字符串类型->(将单字节char*转换为宽字节wchar_t *) 在 MFC 中,AfxMessageBox 默认支持显示 CString 或宽字符字符…...
基于 kubekey -实现懒人一键部署K8S集群
基于 kubekey -实现懒人一键部署K8S集群 操作步骤 官网: https://kubesphere.io/zh/ 一、执行以下命令快速创建一个 Kubernetes 集群。 Master节点 如果您访问 GitHub/Googleapis 受限,请登录 Linux 主机,执行以下命令设置下载区域。 [roott…...
19款超级华丽动画的图片轮播HTML5+CSS3模板源码
大家好,我是分享源码和设计思想的程序媛, 今天给大家分享一个 19款超级华丽动画的图片轮播HTML5CSS3模板源码。 纯CSS3HTML5代码实现,没有任何其它杂乱的框架东西。 图片演示 1. 3D立方体轮播效果 2. 视差滚动轮播效果 3. 卡片堆叠轮播效果 4…...
第十六:redis 的 帖子投票要点
ZADD orders 100 order1 ZADD orders 200 order2 ZADD orders 300 order3 zadd myzset 100 nameorder // 添加一个有序集合 其中存储了用户的订单信息,每个订单用一个唯一的 ID 表示 ZSCORE myzset nameorder // myzset 是key nameorder 是成员ÿ…...
51c深度学习~合集4
我自己的原文哦~ https://blog.51cto.com/whaosoft/12327892 #robustlearn 本文提出了「鲁棒关键微调」,通过「微调」对抗训练模型的「非鲁棒关键性模块」,充分利用其冗余能力提升泛化性。 对抗训练(Adversarail Training)…...
解决Vmware 运行虚拟机Ubuntu22.04卡顿、终端打字延迟问题
亲测可用 打开虚拟机设置,关闭加速3D图形 (应该是显卡驱动的问题,不知道那个版本的驱动不会出现这个问题,所以干脆把加速关了)...
Arduino硬件控制开发基础资料
Arduino 的程序可以划分为三个主要部分:结构、变量(变量与常量)、函数。 结构部分 一、结构 1.1 setup() 1.2 loop() 二、结构控制 2.1 if 2.2 if...else 2.3 for 2.4 switch case 2.5 while 2.6 do... while 2.7 break 2.8 cont…...
地图项目入手学习
如果你目前对自己的地图项目实现原理不太了解,周末可以通过以下方法进行高效学习: ⸻ 第一步:梳理项目相关代码(3 小时) 目标:先大致了解你的地图项目代码,找到核心实现逻辑。 具体做法&…...
OpenCV图像处理:边缘检测
文章目录 前言一、什么是边缘检测?二、算法分类1、Sobel算子2、Scharr算子3、Canny边缘检测3.1 Canny检测的优点3.2 Canny 边缘检测分为 4 个部分3.2.1 、图像降噪3.2.2 、梯度计算3.2.3 、非极大值抑制3.2.4 、双阈值边界跟踪 4、算法比较 三、代码实现总结 前言 …...
性能测试~
1.什么是性能测试 1.什么是性能 就像这两个车一样,虽然都是代步工具,构造都是一样的,但是路虎的发动机要比捷达好.路虎的百米加速却是比捷达快的,我们就知道路虎的性能要比捷达好 . 那么什么是软件的性能呢?我们分析一下 2.常见的性能测试指标 2.1并发数 并发数是指在同一…...
pagehelper 分页插件使用说明
pom.xml:pageHelper坐标 <!--pageHelper坐标--><dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper-spring-boot-starter</artifactId><version>1.4.6</version></dependency> 分…...
使用crypto-js进行DES加/解密
crypto-js 官方网站:https://github.com/brix/crypto-js 中文参考教程:前端加密JS库–CryptoJS 使用指南 在线加解密网站:https://www.mklab.cn/utils/des 首先要安装crypto-js库,根据自己使用的方式按照官方网站步骤进行即可。 …...
【图片识别Excel表格】批量将图片上的区域文字识别后保存为表格,基于WPF和阿里云的项目实战总结
一、项目背景 在信息处理和文档管理中,经常会遇到需要从大量图片中提取文字并进行整理的场景。例如,财务部门需要从大量报销票据中提取金额、日期等信息;法务部门需要从合同文档中提取关键条款;教育行业需要从试卷中提取学生的答题内容等。传统的手工处理方式不仅耗时长、…...
在 i.MX8MP 上用 C++ 调用豆包 AI 大模型实现图像问答
本文介绍了如何在 i.MX8MP 嵌入式平台上使用 C 调用豆包 AI 大模型(Doubao-vision-pro-32k)进行图像问答。我们将详细讲解代码实现的各个步骤,包括文件读取、Base64 编码、构造 JSON 请求体、使用 libcurl 进行 HTTP POST 请求以及解析响应数…...
uni-app自动升级功能
效果图 一、VUE login.vue <template><view><view class"uni-common-mt"><view class"uni-flex uni-column"><view class"flex-item flex-item-V"><view class"logo"><image src"/st…...
线性回归 + 基础优化算法
线性回归 线性回归是机器学习最基础的模型,也是理解后续所有深度学习的基础。 线性模型可以看做是单层神经网络。 上述有个0.5是在求导的时候可以很方便的将2消去。 实际上,这里的数据样本受限很大,比如地球上房子就那么多,肯…...
MyBatis分页插件混用问题解析:IPage与PageHelper的冲突与解决
一、背景 在同时使用 MyBatis-Plus 的 IPage 分页 和 PageHelper 时,开发者可能会遇到以下两类问题: 分页结果异常:IPage 查询的 total 总条数返回 0,但实际数据正常。依赖冲突报错:启动时报错 Column.withColumnNam…...
4.Socket类、InetAddr类、Epoll类实现模块化
目录 1. InetAddr类 类定义 代码说明 类实现 2.Socket类 类定义 类实现 3. Epoll类 类定义 构造与析构函数 方法实现 类实现 4. 使用模块化设计 示例使用(main.cpp) 5. 运行程序 随着程序复杂度的增加,单一的面向过程的代码会变得难以理…...
19 python 模块
在办公室的日常工作中,我们常常会用到各种各样的工具,像计算器用于计算数据、打印机用来打印文件、订书机将纸张装订成册等。这些工具会被反复使用,而且不同的工具具有不同的功能。 一、模块的定义 在 Python 里,模块就如同一个…...
医疗智能体通信整合-大模型训练中沟通优化策略研究
一、引言:医疗模型训练的沟通困境 1.1 医疗 AI 发展背景 在数智化浪潮的推动下,医疗 AI 正以前所未有的速度融入现代医疗体系。从智能影像诊断助力医生精准识别病灶,到基于大数据分析的个性化药物研发,医疗 AI 在提升医疗效率、改善医疗质量方面展现出巨大潜力。据相关数据…...
LearnOpenGL-笔记-其六
今天我们来聊一些更深入的东西: Depth Testing 在之前的学习过程中,我们有接触过深度缓冲,彼时的深度缓冲的意义就是可以让我们体现出深度的差异从而达到立体的效果,而现在我们将在深度缓冲的基础进一步扩展,进行深度…...
【商城实战(91)】安全审计与日志管理:为电商平台筑牢安全防线
【商城实战】专栏重磅来袭!这是一份专为开发者与电商从业者打造的超详细指南。从项目基础搭建,运用 uniapp、Element Plus、SpringBoot 搭建商城框架,到用户、商品、订单等核心模块开发,再到性能优化、安全加固、多端适配…...
Windows 10更新失败解决方法
在我们使用 Windows 时的时候,很多时候遇到系统更新 重启之后却一直提示“我们无法完成更新,正在撤销更改” 这种情况非常烦人,但其实可以通过修改文件的方法解决,并且正常更新到最新版操作系统 01修改注册表 管理员身份运行注…...
【安当产品应用案例100集】042-基于安当KADP实现机密文件安全流转
一、客户需求 某集团公司客户,在系统业务流中,存在大量的内部文件流转的需求。内部业务文件有不同的安全密级,最初在文件流转时,公司内部规定点对点的文件传输,要使用加密工具加密后再发给需要的一方。这种方式虽然能…...
【网络】Socket套接字
目录 一、端口号 二、初识TCP/UDP协议 三、网络字节序 3.1 概念 3.2 常用API 四、Socket套接字 4.1 概念 4.2 常用API (1)socket (2)bind sockaddr结构 (3)listen (4)a…...
蓝桥杯[每日一题] 真题:连连看
题目描述 小蓝正在和朋友们玩一种新的连连看游戏。在一个 n m 的矩形网格中,每个格子中都有一个整数,第 i 行第 j 列上的整数为 Ai, j 。玩家需要在这个网格中寻找一对格子 (a, b) − (c, d) 使得这两个格子中的整数 Aa,b 和 Ac,d 相等,且它…...
新手SEO优化实战快速入门
内容概要 对于SEO新手而言,系统化掌握基础逻辑与实操路径是快速入门的关键。本指南以站内优化为切入点,从网站结构、URL设计到内链布局,逐层拆解搜索引擎友好的技术框架;同时聚焦关键词挖掘与内容策略,结合工具使用与…...
Android面试总结之Glide源码级理解
当你的图片列表在低端机上白屏3秒、高端机因内存浪费导致FPS腰斩时,根源往往藏在Glide的内存分配僵化、磁盘混存、网络加载无优先级三大致命缺陷中。 本文从阿里P8级缓存改造方案出发,结合Glide源码实现动态内存扩容、磁盘冷热分区、智能预加载等黑科技&…...
基于类型属性的重载
算法重载 在一个泛型算法中引入更为特化的变体,这种设计和优化方式称为算法特化。之所以需要算法特化,原因有二: 针对特定类型使用更加合理的实现,对于const char *,less的第二个实现更加合理 template <typename…...
对称加密算法和非对称加密算法
在这个互联网普及的时代,在不同终端对敏感甚至机密数据进行传输是非常常见的场景,但是如何保证数据传输过程的安全性和高效性是一个值得深入探讨的问题。 为此,伟大的人类研究出了多种加密算法,我们可以大致将其分为两类…...
工程数字建造管理系统平台有哪些?好的数字建造管理系统推荐
一、什么是工程数字建造管理系统平台? 工程数字建造管理系统平台是一种集成了先进信息技术(如云计算、大数据、物联网等)的综合性管理工具,它旨在通过数字化手段提升工程建造全过程的管理效率和决策水平。这一平台不仅覆盖了工程…...
CMake ERROR: arm-none-eabi-gcc is not able to compile a simple test program.
用 cmake 构建 STM32 工程问题【已解决】 环境信息 os: ubuntu22.04gcc: arm-none-eabi-gcc (Arm GNU Toolchain 13.2.rel1 (Build arm-13.7)) 13.2.1 20231009cmake: cmake version 3.22.1ninja: 1.10.1 问题 log [main] 正在配置项目: Olidy [driver] 删除 /home/pomegr…...
容器主机CPU使用率突增问题一则
关键词 LINUX、文件系统crontab 、mlocate根目录使用率 There are many things that can not be broken! 如果觉得本文对你有帮助,欢迎点赞、收藏、评论! 一、问题现象 业务一台容器服务器,近期经常收到cpu不定期抖动告警&#x…...
CTFshow【命令执行】web29-web40 做题笔记
web29----过滤关键字 正则匹配,过滤flag,可以使用通配符绕过 先查看目录 使用通配符?查看flag 点击查看源代码 web30---过滤函数和关键字 看到过滤了system执行系统命令和flag,php关键字 找一个与其功能差不多的执行函数passthr…...
L2正则化:优化模型的平滑之道
常见的正则化方法1. **L1正则化(Lasso)**1.1基本原理1.2特点1.3数学推导1.4参数更新1.5选择合适的正则化系数1.6优点1.7缺点1.8实际应用中的注意事项1.9示例 2. **L2正则化(Ridge)**L2正则化的定义L2正则化如何防止过拟合1. **限制…...
Golang 的 GMP 调度机制常见问题及解答
文章目录 Golang GMP 调度模型详解常见问题基础概念1. GMP 各组件的作用是什么?2. 为什么 Go 需要自己的调度器?3. GOMAXPROCS 的作用是什么? 调度流程4. Goroutine 如何被调度到 M 上执行?5. 系统调用会阻塞整个线程吗࿱…...
使用VSCODE导致CPU占用率过高的处理方法
1:cpptools 原因:原因是C/C会在全局搜索文件,可以快速进行跳转;当打开的文件过大,全局搜索文件会占用大量CPU; 处理方法: 1:每次只打开小文件夹; 2:打开大文…...
17--华为防火墙智能选路全解:网络世界的智能导航系统
华为防火墙智能选路全解:网络世界的智能导航系统 开篇故事:快递小哥的烦恼与网络世界的相似性 想象你是个快递站站长,每天要处理来自全国各地的包裹。突然某天遇到: 🚚 双11爆仓:如何把包裹最快送到客户手…...