状态管理方案对比与决策

1. 状态管理的基本概念

现代前端应用随着功能复杂度提升,状态管理已成为架构设计的核心挑战。状态管理本质上解决的是数据的存储、变更追踪和响应式更新问题,以确保UI与底层数据保持同步。

核心挑战:

  • 状态共享与组件通信
  • 可预测的状态变更
  • 性能优化与重渲染控制
  • 异步状态处理
  • 开发体验与调试便利性

2. 主流状态管理方案对比

Redux

核心原理:
基于单向数据流和不可变状态的Flux架构实现。全局维护一个状态树,通过dispatch action触发reducer函数来更新状态。

// Store 创建
import { createStore } from 'redux';const initialState = { counter: 0 };
const reducer = (state = initialState, action) => {switch (action.type) {case 'INCREMENT':return { ...state, counter: state.counter + 1 };default:return state;}
};const store = createStore(reducer);// 使用示例
store.dispatch({ type: 'INCREMENT' });
console.log(store.getState()); // { counter: 1 }// React组件中使用
import { useSelector, useDispatch } from 'react-redux';function Counter() {const counter = useSelector((state) => state.counter);const dispatch = useDispatch();return (<div><span>{counter}</span><button onClick={() => dispatch({ type: 'INCREMENT' })}>+</button></div>);
}

优势:

  • 可预测性高:状态变更过程清晰可追踪
  • 强大的开发者工具生态支持(Redux DevTools)
  • 中间件系统便于扩展(redux-thunk, redux-saga等)
  • 大型社区和丰富的学习资源
  • 适合复杂状态逻辑和多人协作场景

缺陷:

  • 模板代码较多(actions, reducers, selectors)
  • 学习曲线陡峭
  • 小型应用显得过度工程化
  • 异步处理需要额外中间件

MobX

核心原理:
基于可观察对象(Observable)实现响应式状态管理,通过注解或函数包装使普通对象具备响应式特性。

// 定义状态
import { makeObservable, observable, action, computed } from 'mobx';
import { observer } from 'mobx-react-lite';class CounterStore {constructor() {makeObservable(this, {count: observable,increment: action,doubleCount: computed});}count = 0;increment() {this.count++;}get doubleCount() {return this.count * 2;}
}const counterStore = new CounterStore();// React组件中使用
const CounterView = observer(() => {return (<div><span>Count: {counterStore.count}</span><span>Double: {counterStore.doubleCount}</span><button onClick={() => counterStore.increment()}>+</button></div>);
});

优势:

  • 更少的模板代码,直观的API
  • 优秀的性能表现,精确的组件重渲染控制
  • 面向对象编程模型,更接近传统开发思维
  • 自动追踪依赖关系,无需手动优化

缺陷:

  • 状态变更不够明确,调试难度较高
  • 学习响应式概念有一定门槛
  • 装饰器语法在JavaScript生态中标准化程度不高
  • 需要谨慎处理observable对象以避免性能问题

Recoil

核心原理:
Facebook开发的专为React设计的原子化状态管理库,通过atom和selector概念构建状态依赖图。

// 定义状态
import { atom, selector, useRecoilState, useRecoilValue } from 'recoil';const counterState = atom({key: 'counterState',default: 0,
});const doubleCountState = selector({key: 'doubleCountState',get: ({get}) => {const count = get(counterState);return count * 2;},
});// React组件中使用
function Counter() {const [count, setCount] = useRecoilState(counterState);const doubleCount = useRecoilValue(doubleCountState);return (<div><span>Count: {count}</span><span>Double: {doubleCount}</span><button onClick={() => setCount(count + 1)}>+</button></div>);
}

优势:

  • 原子化状态设计,精细控制组件订阅
  • 与React Concurrent Mode兼容设计
  • 内置对异步状态和派生状态的支持
  • 类React Hooks的API设计,学习成本低
  • 良好的代码分离支持,适合代码分割

缺陷:

  • 相对年轻,生态系统和社区支持有限
  • 需要RecoilRoot上下文包裹
  • 大型应用中atom键名管理挑战
  • 未明确支持服务端渲染

Zustand

核心原理:
基于hook的轻量级状态管理库,通过创建独立store并提供选择性订阅机制。

// 创建store
import create from 'zustand';const useStore = create((set) => ({count: 0,increment: () => set((state) => ({ count: state.count + 1 })),
}));// React组件中使用
function Counter() {const count = useStore((state) => state.count);const increment = useStore((state) => state.increment);return (<div><span>{count}</span><button onClick={increment}>+</button></div>);
}

优势:

  • 极简API设计,几乎无模板代码
  • 不需要Provider包裹组件
  • 中间件系统支持(redux-devtools, immer, persist等)
  • 优秀的性能表现,内置状态访问优化
  • 支持多store设计

缺陷:

  • 对大型状态结构的管理不如Redux系统化
  • 状态共享模式需要自行设计
  • 相对较新,生产环境验证案例较少
  • 文档相对简洁

3. 实例分析:不同场景下的状态管理选择

场景一:大型企业应用

特点:多人协作、复杂业务逻辑、严格的状态变更控制需求

最佳选择:Redux + Redux Toolkit

// 使用Redux Toolkit简化Redux开发
import { createSlice, configureStore } from '@reduxjs/toolkit';const counterSlice = createSlice({name: 'counter',initialState: { value: 0 },reducers: {increment: (state) => {// RTK允许在reducer中直接修改状态,内部使用Immerstate.value += 1;}}
});export const { increment } = counterSlice.actions;
const store = configureStore({reducer: {counter: counterSlice.reducer}
});

实施原因

  • 明确的状态管理模式便于团队协作和规范执行
  • 完备的中间件生态满足复杂业务需求
  • DevTools提供完整的状态变更追踪,便于调试
  • Redux Toolkit减少样板代码,降低学习门槛

场景二:中型SPA应用

特点:中等复杂度、注重开发效率、需要精细控制渲染性能

最佳选择:MobX

// 使用MobX状态树(MST)增强类型安全和结构化状态
import { types, flow, onSnapshot } from 'mobx-state-tree';const UserStore = types.model('UserStore', {users: types.array(types.model({id: types.identifier,name: types.string})),loading: types.optional(types.boolean, false)}).actions(self => ({fetchUsers: flow(function* () {self.loading = true;try {const response = yield fetch('/api/users');const data = yield response.json();self.users = data;} finally {self.loading = false;}})}));const store = UserStore.create({ users: [] });
onSnapshot(store, snapshot => console.log('New state:', snapshot));

实施原因

  • 响应式设计显著减少重渲染,提升应用性能
  • 更自然的编程模型降低开发负担
  • 衍生值和反应能力简化状态依赖管理
  • 良好封装的异步流程处理

场景三:轻量级应用或组件库

特点:注重体积和启动性能、简洁明了的API需求

最佳选择:Zustand

// 创建多个独立store并实现通信
import create from 'zustand';
import { devtools, persist } from 'zustand/middleware';// 用户认证store
const useAuthStore = create(persist(devtools((set) => ({user: null,login: (userData) => set({ user: userData }),logout: () => set({ user: null })})),{ name: 'auth-storage' })
);// 购物车store
const useCartStore = create((set, get) => ({items: [],addItem: (item) => set((state) => ({ items: [...state.items, item] })),checkout: async () => {const authStore = useAuthStore.getState();if (!authStore.user) {throw new Error('Must login first');}// 处理结账逻辑...}
}));

实施原因

  • 极简API设计最小化学习成本
  • 无Provider要求简化应用结构
  • 包体积小,适合性能敏感场景
  • 灵活的store设计适合按功能模块拆分状态

场景四:实验性功能或需要细粒度状态控制

特点:需要React并发特性、原子化状态需求

最佳选择:Recoil

// 实现复杂的异步数据流和结构化状态处理
import { atom, selector, selectorFamily, useRecoilValue } from 'recoil';// 基础状态
const userIdState = atom({key: 'userId',default: 1
});// 异步派生状态
const userInfoQuery = selectorFamily({key: 'userInfo',get: (userId) => async () => {const response = await fetch(`/api/users/${userId}`);return response.json();}
});// 组合多个状态
const userWithPostsSelector = selector({key: 'userWithPosts',get: async ({get}) => {const userId = get(userIdState);const user = await get(userInfoQuery(userId));const postsResponse = await fetch(`/api/users/${userId}/posts`);const posts = await postsResponse.json();return { ...user, posts };}
});function UserProfile() {const userData = useRecoilValue(userWithPostsSelector);// 渲染用户数据...
}

实施原因

  • 原子化设计减少不必要的重渲染
  • 内置异步状态处理简化数据获取逻辑
  • 与React Suspense自然集成
  • 适合实验性功能和新特性尝试

4. 项目选型决策框架

4.1 评估维度权重模型

评估维度ReduxMobXRecoilZustand
可预测性★★★★★★★★☆☆★★★★☆★★★★☆
性能优化★★★☆☆★★★★★★★★★☆★★★★★
学习曲线★★☆☆☆★★★☆☆★★★★☆★★★★★
开发效率★★☆☆☆★★★★☆★★★★☆★★★★★
调试能力★★★★★★★★☆☆★★★★☆★★★★☆
社区支持★★★★★★★★★☆★★★☆☆★★★☆☆
扩展能力★★★★★★★★☆☆★★★☆☆★★★★☆
代码量★★☆☆☆★★★★☆★★★★☆★★★★★

4.2 选型决策

  1. 项目规模判断

    • 大型企业级应用 → Redux + RTK
    • 中小型应用 → 继续评估
  2. 团队因素考量

    • 团队熟悉Redux生态 → Redux + RTK
    • 倾向OOP编程模式 → MobX
    • 习惯React Hooks → Zustand/Recoil
  3. 性能需求评估

    • 复杂UI与大量状态依赖 → MobX/Recoil
    • 对包大小和启动速度敏感 → Zustand
  4. 状态复杂度分析

    • 深层嵌套状态结构 → Redux + Immer
    • 独立原子化状态需求 → Recoil
    • 简单扁平状态结构 → Zustand
  5. 开发体验优先级

    • 强调简洁API和快速开发 → Zustand
    • 注重可测试性和状态追踪 → Redux
    • 需要细粒度控制和异步流程 → MobX/Recoil

5. 关键样例分析

5.1 异步状态处理对比

Redux (使用Redux Toolkit):

import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';export const fetchUsers = createAsyncThunk('users/fetchUsers',async () => {const response = await fetch('/api/users');return response.json();}
);const usersSlice = createSlice({name: 'users',initialState: {entities: [],loading: false,error: null},reducers: {},extraReducers: (builder) => {builder.addCase(fetchUsers.pending, (state) => {state.loading = true;}).addCase(fetchUsers.fulfilled, (state, action) => {state.loading = false;state.entities = action.payload;}).addCase(fetchUsers.rejected, (state, action) => {state.loading = false;state.error = action.error.message;});}
});

MobX:

import { makeAutoObservable, runInAction } from 'mobx';class UsersStore {users = [];loading = false;error = null;constructor() {makeAutoObservable(this);}async fetchUsers() {this.loading = true;this.error = null;try {const response = await fetch('/api/users');const data = await response.json();runInAction(() => {this.users = data;this.loading = false;});} catch (error) {runInAction(() => {this.error = error.message;this.loading = false;});}}
}

Zustand:

import create from 'zustand';const useUsersStore = create((set) => ({users: [],loading: false,error: null,fetchUsers: async () => {set({ loading: true, error: null });try {const response = await fetch('/api/users');const users = await response.json();set({ users, loading: false });} catch (error) {set({ error: error.message, loading: false });}}
}));

Recoil:

import { atom, selector, useRecoilValueLoadable } from 'recoil';const usersQueryAtom = atom({key: 'UsersQuery',default: null,
});const usersResultSelector = selector({key: 'UsersResult',get: async ({get}) => {get(usersQueryAtom); // 触发依赖追踪const response = await fetch('/api/users');if (!response.ok) {throw new Error('Network error');}return response.json();}
});function UsersList() {const usersLoadable = useRecoilValueLoadable(usersResultSelector);switch(usersLoadable.state) {case 'loading':return <div>Loading...</div>;case 'hasError':return <div>Error: {usersLoadable.contents.message}</div>;case 'hasValue':return (<ul>{usersLoadable.contents.map(user => (<li key={user.id}>{user.name}</li>))}</ul>);}
}

5.2 状态共享和模块化设计

Redux (使用Redux Toolkit):

// 定义多个状态切片
const userSlice = createSlice({/*...*/});
const cartSlice = createSlice({/*...*/});
const orderSlice = createSlice({/*...*/});// 合并到根reducer
const rootReducer = combineReducers({user: userSlice.reducer,cart: cartSlice.reducer,order: orderSlice.reducer
});// 创建store
const store = configureStore({reducer: rootReducer
});// 状态选择器
const selectCartTotal = (state) => {return state.cart.items.reduce((total, item) => total + item.price * item.quantity, 0);
};// 跨状态操作
const checkoutThunk = () => (dispatch, getState) => {const state = getState();// 检查用户是否已登录if (!state.user.isLoggedIn) {dispatch(openLoginModal());return;}// 将购物车内容转为订单const order = {items: state.cart.items,total: selectCartTotal(state),userId: state.user.id};dispatch(createOrder(order));dispatch(clearCart());
};

Zustand (模块化设计):

// 创建多个独立但可互操作的store
const useUserStore = create((set) => ({/*...*/}));
const useCartStore = create((set, get) => ({/*...*/}));
const useOrderStore = create((set, get) => ({/*...*/}));// 创建派生状态
const useCartTotal = () => {return useCartStore(state => state.items.reduce((total, item) => total + item.price * item.quantity, 0));
};// 跨store操作
function useCheckout() {const userState = useUserStore();const { items, clearCart } = useCartStore();const { createOrder } = useOrderStore();const total = useCartTotal();return () => {if (!userState.isLoggedIn) {userState.openLoginModal();return;}const order = {items,total,userId: userState.id};createOrder(order);clearCart();};
}

6. 未来趋势

6.1 状态管理发展方向

  1. React状态原生化

    • React内置hooks如useReducer和useContext不断增强
    • 状态管理逐渐向框架层面整合,减少外部依赖
  2. 原子化状态模型崛起

    • 细粒度状态控制成为主流设计模式
    • 更精确的组件重渲染控制与优化
  3. 去中心化状态架构

    • 从全局单一状态树转向模块化、独立状态设计
    • 按需加载状态逻辑,更好支持代码分割
  4. 不可变数据结构优化

    • 像Immer这样的不可变性工具成为标配
    • 平衡不可变性和性能的新方案涌现
  5. 异步状态处理标准化

    • 异步状态管理模式趋于统一和简化
    • 与React Suspense等新特性深度整合

6.2 项目迁移与混合方案

状态管理迁移策略:

  1. 渐进式迁移

    • 识别应用中独立的功能模块
    • 从非核心功能开始替换状态管理方案
    • 设计适配层以确保新旧状态管理方案协同工作
  2. 混合状态架构

// Redux核心状态与Zustand局部状态混合使用示例// 全局Redux状态
import { Provider } from 'react-redux';
import { configureStore } from '@reduxjs/toolkit';
import rootReducer from './reducers';const store = configureStore({reducer: rootReducer
});// Zustand局部状态
import create from 'zustand';const useLocalFormState = create((set) => ({formData: {},updateField: (field, value) => set(state => ({formData: { ...state.formData, [field]: value }}))
}));// 组件中的混合使用
function ComplexForm() {// 全局Redux状态const user = useSelector(state => state.user);const dispatch = useDispatch();// 局部Zustand状态const { formData, updateField } = useLocalFormState();const handleSubmit = () => {// 提交前验证可访问两种状态if (!user.isLoggedIn) {dispatch(redirectToLogin());return;}dispatch(submitFormAction({...formData,userId: user.id}));};// 渲染表单...
}

7. 结语

状态管理选型应基于项目规模、团队特点、性能要求和业务复杂度进行综合评估,不存在"银弹"般的解决方案。

同时随着前端生态不断演进,保持对状态管理新趋势的理解与实践尝试,也能帮助团队在复杂应用开发中作出更明智的技术选择。

实践应该从小规模尝试开始,同时确保团队完全理解所选方案的优缺点,并建立清晰的状态设计规范,以确保长期的代码可维护性。

8. 参考资源

官方文档和指南

  • Redux

    • Redux官方文档
    • Redux Toolkit指南
    • Redux风格指南
  • MobX

    • MobX官方文档
    • MobX-State-Tree指南
    • MobX响应式原理解析
  • Recoil

    • Recoil官方文档
    • Recoil入门指南
    • Recoil核心概念
  • Zustand

    • Zustand GitHub仓库
    • Zustand使用指南
    • Zustand中间件文档

深度技术文章和博客

  • 比较现代React状态管理库
  • Redux、MobX与Context API: 何时选择什么?
  • React状态管理性能对比
  • Recoil原子化状态设计理念分析
  • 为什么Zustand正在超越Redux
  • 异步状态管理实践

教程

  • Redux完全指南 (Maximilian Schwarzmüller)
  • MobX与React: 构建响应式应用
  • Recoil从入门到精通
  • Zustand实用教程
  • React Query与状态管理整合

示例项目和代码库

  • Redux Real-World示例
  • MobX-TodoMVC
  • Recoil示例集合
  • Zustand实战项目
  • 不同状态管理方案对比项目

工具和扩展

  • Redux DevTools
  • MobX DevTools
  • Recoilize开发者工具
  • React Query DevTools
  • Immer.js - 不可变数据处理库

社区资源和论坛

  • React官方讨论状态管理的Issue
  • React状态管理最佳实践调查结果
  • 状态管理技术讨论组
  • React状态管理性能基准测试
  • 2023年React状态管理趋势报告

书籍

  • 《Learning Redux》- Daniel Bugl
  • 《Managing React State》- Cory House
  • 《MobX Quick Start Guide》- Pavan Podila & Michel Weststrate
  • 《React设计模式与最佳实践》- Michele Bertoli

如果你觉得这篇文章有帮助,欢迎点赞收藏,也期待在评论区看到你的想法和建议!👇

终身学习,共同成长。

咱们下一期见

💻

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/diannao/86692.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Fetch与Axios:区别、联系、优缺点及使用差异

Fetch与Axios&#xff1a;区别、联系、优缺点及使用差异 文章目录 Fetch与Axios&#xff1a;区别、联系、优缺点及使用差异一、联系二、区别1. 浏览器支持与兼容性2. 响应处理3. 请求拦截和响应拦截4. 错误处理 三、优缺点1. Fetch API优点缺点 2. Axios优点缺点 四、使用上的差…

【Docker】快速入门与项目部署实战

我们在部署一个项目时&#xff0c;会出现一系列问题比如&#xff1a; 命令太多了&#xff0c;记不住软件安装包名字复杂&#xff0c;不知道去哪里找安装和部署步骤复杂&#xff0c;容易出错 其实上述问题不仅仅是新手&#xff0c;即便是运维在安装、部署的时候一样会觉得麻烦…

Java面试题尚硅谷版第1季

1、写出如下代码运行结果 1.1、 使用局部变量表和操作数栈解题 1.2、使用前置和后置递增解题 2、写一个单例模式 2.1、考察知识点 2.2、单例模式实现 3、类加载和初始化顺序 package classload;public class Father {private int i test();private static int j method();st…

关于Qt阻断样式继承的解决办法

引言 在使用 Qt 开发桌面应用时&#xff0c;借助样式表&#xff08;StyleSheet&#xff09;来统一定义界面风格是非常常见的做法。通常&#xff0c;你会在主程序中通过 qApp->setStyleSheet(...) 或者直接给某个父控件设置样式表&#xff0c;让所有的子控件都采用相同的配色…

鼠标右键添加新建某种文件的方法

场景 我经常用到.emmx&#xff0c;.eddx文件&#xff0c;电脑上装的是wpsX亿图&#xff08;因为有wps会员&#xff09;&#xff0c;没有开亿图会员。 然后问题就是&#xff0c;思维导图和流程图我都能正常开&#xff0c;正常编辑&#xff0c;但鼠标右键没有新建这两个文件的按…

Inxpect安全雷达传感器与控制器:动态检测 + 抗干扰技术重构工业安全防护体系

Inxpect 推出工业安全领域新型智能传感器与控制器&#xff0c;其核心产品为雷达扫描仪&#xff0c;具备动态调整检测区域、抗干扰能力强等特点&#xff0c;可精准检测危险区域人员进入或存在情况&#xff0c;适用于移动机器人等场景。 Inxpect安全雷达传感器核心功能 动态检测…

【AI学习】李广密与阶跃星辰首席科学家张祥雨对谈:多模态发展的历史和未来

仔细阅读了文章《专访张祥雨&#xff1a;多模态推理和自主学习是未来的 2 个 「GPT-4」 时刻》 https://mp.weixin.qq.com/s/892QuRPH9uP6zN6dS-HZMw 非常赞叹的一篇文章&#xff0c;说清楚了NLP、CV发展中的许多重大问题&#xff0c;读来醍醐灌顶&#xff01;这样的文章&…

C++中std::deque详解和实战工程代码示例

C中std::deque详解和实战工程代码示例 std::deque&#xff08;双端队列&#xff09;是 C 标准库中的一个序列容器&#xff0c;与 std::vector 类似&#xff0c;但它支持从头部和尾部高效地插入和删除元素。它底层采用分段连续空间实现&#xff0c;兼具灵活性与性能。 一、基本…

【AI大模型入门指南】概念与专有名词详解 (二)

【AI大模型入门指南】概念与专有名词详解 &#xff08;二&#xff09; 一 、前言 当你和聊天机器人聊得天花乱坠时&#xff0c;当你用文字让AI生成精美图片时&#xff0c;当手机相册自动帮你分类照片时 —— 这些看似智能的操作背后&#xff0c;都藏着 AI 大模型的身影。 本…

AIStor 的模型上下文协议 (MCP) 服务器:管理功能

在本系列的上一篇博文中&#xff0c;我们讨论了 MinIO AIStor 的模型上下文协议 (MCP) 服务器的基本用户级功能。我们学习了如何使用人类语言命令查看存储桶的内容、分析对象并标记它们以便将来处理&#xff0c;以及如何通过 LLM&#xff08;例如 Anthropic Claude&#xff09;…

期权末日轮实值期权盈利未平仓怎么办?

本文主要介绍期权末日轮实值期权盈利未平仓怎么办&#xff1f;期权末日轮实值期权盈利未平仓该怎么办&#xff0c;需要明确几个关键点&#xff1a;末日轮指的是期权到期日临近的时候&#xff0c;通常指最后一周&#xff0c;尤其是最后一天&#xff0c;这时候时间价值衰减很快&a…

C++/Qt 联合编程中的定时器使用陷阱:QObject::startTimer 报错详解

在 Qt 开发中&#xff0c;QTimer 是一个常用的工具类&#xff0c;用于处理定时事件。但不少开发者在 C/Qt 联合编程&#xff0c;尤其是在工具类、静态类、线程中使用定时器时&#xff0c;会遇到如下令人困惑的报错&#xff1a; QObject::startTimer: Timers can only be used …

CentOS7.9 查询运维安全日志,排查恶意用户

1、查看系统版本 cat /etc/redhat-release uname -a 2、查看所有账号 cat /etc/shadow 3、修改 root 密码 passwd 3、查看账号ID id jinzhi 4、查看登录日志 lastlog 5、查看操作日志 cat .bash_history sudo cat /home/yunwei/.bash_history sudo grep root /va…

多模态大语言模型arxiv论文略读(117)

Training-free Zero-shot Composed Image Retrieval via Weighted Modality Fusion and Similarity ➡️ 论文标题&#xff1a;Training-free Zero-shot Composed Image Retrieval via Weighted Modality Fusion and Similarity ➡️ 论文作者&#xff1a;Ren-Di Wu, Yu-Yen L…

如何正确的配置eureka server集群

将 Eureka Server 实例的 hostname 都配置成相同的值&#xff0c;在 Eureka Server 集群环境下同样是不推荐且通常会导致严重问题的&#xff0c; 核心问题&#xff1a;Eureka Server 集群的工作机制 Eureka Server 集群通过相互注册&#xff08;Peering&#xff09;来实现高可…

AI支持下的-ArcGIS数据处理、空间分析、可视化及多案例综合应用

查看原文>>> 从入门到精通-AI支持下的-ArcGIS数据处理、空间分析、可视化及多案例综合应用 结合ArcGIS和GPT的优势&#xff0c;本文重点进行AI大模型应用、ArcGIS工作流程及功能、Prompt使用技巧、AI助力工作流程、AI助力数据读取与处理、AI助力空间分析、AI助力遥感…

vue3-ts: v-model 和 props 的关系

在 Vue.js 中&#xff0c;v-model 是一个语法糖&#xff0c;它实际上是 :value 和 input 事件的组合。 当你使用 v-model 绑定一个组件时&#xff0c;默认情况下&#xff0c;组件会通过 props 接收 value 这个 prop&#xff0c; 并通过触发 input 事件来更新父组件中的数据。 …

学车笔记 变挡

超15就可以加一档了 有些人对手动挡的档位有一些误解_哔哩哔哩_bilibili 献给所有新司机.开手动档摆脱顿挫的根本方法.学会看转速!没那么复杂!_哔哩哔哩_bilibili 减速到怠速降一档

STM32的DMA简介

STM32的DMA简介 一、DMA概述 DMA&#xff08;Direct Memory Access&#xff0c;直接存储器存取&#xff09;是一种硬件机制&#xff0c;它允许外设和存储器之间或者存储器和存储器之间进行高速数据传输&#xff0c;而无需CPU的干预。这种机制可以极大地节省CPU资源&#xff0c…

Spring-AOP知识点

一、AOP简介 1.AOP概念 2.AOP思想实现方案 3.AOP相关概念 二、基于xml配置AOP 1.快速入门 2.AOP配置详解 3.AOP原理剖析 三、基于注解配置AOP 1.快速入门 2.注解方式AOP配置详解 抽取切点表达式