From eb49928833807fa817a3b9300ff853e3c0c52525 Mon Sep 17 00:00:00 2001 From: bunny <1319900154@qq.com> Date: Thu, 19 Jun 2025 12:44:04 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20Vuex=20=E7=8A=B6=E6=80=81=E7=AE=A1?= =?UTF-8?q?=E7=90=86=E6=9C=80=E4=BD=B3=E5=AE=9E=E8=B7=B5=E6=8C=87=E5=8D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../single-file/demo2/src/store/index.js | 3 +- .../demo2/src/store/modules/count.js | 41 ++++ .../views/demo4/Vuex 状态管理最佳实践指南.md | 178 ++++++++++++++++++ .../src/views/demo4/compontens/Count.vue | 21 +-- 4 files changed, 228 insertions(+), 15 deletions(-) create mode 100644 vue2-tutorials/single-file/demo2/src/store/modules/count.js create mode 100644 vue2-tutorials/single-file/demo2/src/views/demo4/Vuex 状态管理最佳实践指南.md diff --git a/vue2-tutorials/single-file/demo2/src/store/index.js b/vue2-tutorials/single-file/demo2/src/store/index.js index 63e861a..6fedd6b 100644 --- a/vue2-tutorials/single-file/demo2/src/store/index.js +++ b/vue2-tutorials/single-file/demo2/src/store/index.js @@ -1,12 +1,13 @@ import Vue from "vue"; import Vuex from "vuex"; +import count from "./modules/count"; Vue.use(Vuex); const store = new Vuex.Store({ state: {}, mutations: {}, actions: {}, - modules: {}, + modules: { count }, }); export default store; diff --git a/vue2-tutorials/single-file/demo2/src/store/modules/count.js b/vue2-tutorials/single-file/demo2/src/store/modules/count.js new file mode 100644 index 0000000..1305d2f --- /dev/null +++ b/vue2-tutorials/single-file/demo2/src/store/modules/count.js @@ -0,0 +1,41 @@ +import Vue from "vue"; +import Vuex from "vuex"; +Vue.use(Vuex); + +const count = { + namespaced: true, + state: { num: 1, sum: 0 }, + actions: { + // 奇数相加 + incrementOdd(context) { + // 可以从上下文中获取sum + if (context.state.sum % 2) { + context.commit("INCREMENT_ODD"); + } + }, + incrementWait(context) { + setTimeout(() => { + context.commit("INCREMENT_WAIT"); + }, 500); + }, + }, + mutations: { + // 相加 + INCREMENT(state) { + state.sum += state.num; + }, + // 相减 + DECREMENT(state) { + state.sum -= state.num; + }, + // 奇数相加 + INCREMENT_ODD(state) { + state.sum += state.num; + }, + INCREMENT_WAIT(state) { + state.sum += state.num; + }, + }, +}; + +export default count; diff --git a/vue2-tutorials/single-file/demo2/src/views/demo4/Vuex 状态管理最佳实践指南.md b/vue2-tutorials/single-file/demo2/src/views/demo4/Vuex 状态管理最佳实践指南.md new file mode 100644 index 0000000..5dadb0e --- /dev/null +++ b/vue2-tutorials/single-file/demo2/src/views/demo4/Vuex 状态管理最佳实践指南.md @@ -0,0 +1,178 @@ +# Vuex 状态管理最佳实践指南 + +## 一、核心架构解析 + +### 1. 模块化结构 +```javascript +// store/index.js - 主入口文件 +import count from './modules/count' + +export default new Vuex.Store({ + modules: { + count // 启用命名空间的计数模块 + } +}) + +// store/modules/count.js - 计数模块 +export default { + namespaced: true, // 启用命名空间 + state: { + num: 1, + sum: 0 + }, + mutations: { /* 同步操作 */ }, + actions: { /* 异步操作 */ } +} +``` + +### 2. 数据流示意图 +``` +组件 → dispatch → Actions → commit → Mutations → mutate → State → 响应式更新 → 组件 +``` + +## 二、代码优化建议 + +### 1. 组件中的优化 +```javascript +// 使用map辅助函数简化代码 +import { mapActions, mapMutations, mapState } from 'vuex' + +export default { + computed: { + ...mapState('count', ['sum', 'num']) + }, + methods: { + ...mapMutations('count', ['INCREMENT', 'DECREMENT']), + ...mapActions('count', ['incrementOdd', 'incrementWait']) + } +} +``` + +### 2. Store 中的优化 +```javascript +// 使用常量替代字符串 mutation 类型 +const types = { + INCREMENT: 'INCREMENT', + DECREMENT: 'DECREMENT' +} + +const count = { + mutations: { + [types.INCREMENT](state) { + state.sum += state.num + } + } +} +``` + +## 三、最佳实践规范 + +### 1. 命名规范 +| 类型 | 命名风格 | 示例 | +| -------- | ------------ | ----------------- | +| Mutation | 大写+下划线 | `INCREMENT` | +| Action | camelCase | `fetchData` | +| Getter | 形容词/名词 | `filteredList` | +| Module | 业务相关名词 | `user`, `product` | + +### 2. 操作分离原则 +- **Mutations**: + - 只做简单状态赋值 + - 必须是同步函数 + - 命名类似事件(`SET_USER_INFO`) + +- **Actions**: + - 处理业务逻辑 + - 可以包含异步操作 + - 命名类似方法(`fetchUserData`) + +### 3. 模块化建议 +1. 按功能/业务划分模块 +2. 每个模块启用命名空间 +3. 模块内维护独立state + +## 四、高级应用场景 + +### 1. 动态模块注册 +```javascript +// 在需要时加载模块 +store.registerModule('dynamicModule', { + // 模块定义 +}) +``` + +### 2. 表单处理方案 +```javascript +// 使用双向绑定计算属性 +computed: { + num: { + get() { return this.$store.state.count.num }, + set(value) { this.$store.commit('count/UPDATE_NUM', value) } + } +} +``` + +### 3. 插件开发 +```javascript +// 持久化插件示例 +const persistPlugin = store => { + store.subscribe((mutation, state) => { + localStorage.setItem('vuex_state', JSON.stringify(state)) + }) +} +``` + +## 五、性能优化技巧 + +### 1. 大型状态树 +- 使用模块懒加载 +- 避免在state中存储大对象 + +### 2. 计算属性缓存 +```javascript +getters: { + bigSum: state => { + // 复杂计算会被缓存 + return heavyCalculation(state.sum) + } +} +``` + +### 3. 批量更新 +```javascript +// 合并多个mutation +actions: { + bulkUpdate({ commit }, payload) { + commit('UPDATE_A', payload.a) + commit('UPDATE_B', payload.b) + } +} +``` + +## 六、常见问题解决方案 + +1. **热重载问题**: + ```javascript + if (module.hot) { + module.hot.accept(['./modules/count'], () => { + store.hotUpdate({ modules: { count } }) + }) + } + ``` + +2. **循环依赖**: + - 避免模块间互相引用 + - 使用全局事件总线处理跨模块通信 + +3. **调试技巧**: + - 使用Vue Devtools追踪状态变化 + - 添加logger插件记录mutation + +## 七、与Vue3的Pinia对比 + +| 特性 | Vuex | Pinia | +| ---------- | ------------ | -------- | +| 语法 | 较复杂 | 更简洁 | +| 模块化 | 需要配置 | 自动支持 | +| TypeScript | 需要额外配置 | 完美支持 | +| 体积 | 较大 | 更轻量 | diff --git a/vue2-tutorials/single-file/demo2/src/views/demo4/compontens/Count.vue b/vue2-tutorials/single-file/demo2/src/views/demo4/compontens/Count.vue index 28e6ba7..9ead57e 100644 --- a/vue2-tutorials/single-file/demo2/src/views/demo4/compontens/Count.vue +++ b/vue2-tutorials/single-file/demo2/src/views/demo4/compontens/Count.vue @@ -1,7 +1,7 @@