Vuex 教程 从入门到实践

​一 核心概念与适用场景​

  • ​Vuex​​Vue.js​​集中式状态管理​ 库,采用​单一状态树​ ,以可预测的方式管理应用中多个组件共享的数据。其核心包含五部分:​State​ (状态)、​Getters​ (派生状态)、​Mutations​ (同步修改)、​Actions​ (异步调度)、​Modules​ (模块化)。适用于​跨多组件共享数据​​复杂表单​​购物车/登录状态​​路由守卫依赖的全局状态​ 等场景。数据流遵循:组件触发 ​Action​​Action​ 执行异步并提交 ​Mutation​​Mutation​ 同步修改 ​State​ → 视图响应更新。

​二 环境搭建与项目结构​

  • 安装(Vue 2 项目):执行命令:npm install vuex@3 --save(Vuex 3 适配 Vue 2)。

  • 目录结构建议:

    javascript 复制代码
    src/
    ├── store/
    │   ├── index.js          # 创建 store 实例
    │   ├── state.js          # 全局状态
    │   ├── mutations.js      # 同步修改
    │   ├── actions.js        # 异步操作
    │   ├── getters.js        # 派生数据
    │   └── modules/          # 模块化(可选)
    │       ├── cart.js
    │       └── user.js
    └── main.js               # 引入并注入 store
  • ​main.js​ 中注册:

    javascript 复制代码
    import Vue from 'vue';
    import App from './App.vue';
    import store from './store'; // 路径按项目实际调整
    
    new Vue({ store, render: h => h(App) }).$mount('#app');
  • 说明:在 ​Vue 3​ 项目中应使用 ​Pinia​ (官方推荐),如需使用 Vuex 则选择 ​Vuex 4​

​三 核心 API 与使用示例​

  • State

    • 定义(store/state.js):

      javascript 复制代码
      export default {
        count: 0,
        user: { name: 'Guest' }
      };
    • 读取(组件内):this.$store.state.count

  • Getters

    • 定义(store/getters.js):

      javascript 复制代码
      export default {
        doubleCount: state => state.count * 2,
        userName: state => state.user.name
      };
    • 读取:this.$store.getters.doubleCount

  • Mutations(同步修改,唯一途径)

    • 定义(store/mutations.js):

      javascript 复制代码
      export default {
        INCREMENT(state, payload) {
          state.count += (payload?.step || 1);
        },
        SET_USER(state, user) {
          state.user = { ...state.user, ...user };
        }
      };
    • 提交:this.$store.commit('INCREMENT', { step: 5 })

  • Actions(异步调度,提交 Mutation)

    • 定义(store/actions.js):

      javascript 复制代码
      export default {
        incrementAsync({ commit }, payload) {
          return new Promise(resolve => {
            setTimeout(() => {
              commit('INCREMENT', payload);
              resolve();
            }, 1000);
          });
        },
        async login({ commit }, { username }) {
          // 模拟 API
          const user = await fakeApiLogin(username);
          commit('SET_USER', user);
        }
      };
    • 派发:this.$store.dispatch('incrementAsync', { step: 2 })

  • 辅助函数(简化模板与代码)

    javascript 复制代码
    import { mapState, mapGetters, mapMutations, mapActions } from 'vuex';
    
    export default {
      computed: {
        // 数组写法
        ...mapState(['count', 'user']),
        ...mapGetters(['doubleCount', 'userName']),
        // 对象写法(可重命名)
        ...mapState('cart', ['items']) // 模块化时
      },
      methods: {
        // 数组写法
        ...mapMutations(['INCREMENT']),
        ...mapActions(['incrementAsync']),
        // 对象写法(可重命名)
        ...mapActions('cart', { addToCart: 'ADD_ITEM' })
      }
    };
  • 要点:​Mutation 必须是同步函数​​Action 可包含异步​ ,并通过 commit 改变状态;在组件中优先使用​辅助函数​​Composition API​ 风格的 useStore()(Vuex 3/4 提供)。

​四 模块化与命名空间​

  • 当项目变大,建议按功能拆分模块,避免单一文件臃肿,并开启​命名空间​以隔离命名冲突与提升可维护性。

  • 示例:创建 store/modules/counter.js

    javascript 复制代码
    const counter = {
      namespaced: true, // 开启命名空间
      state: () => ({ value: 0 }),
      mutations: {
        UP(state, n = 1) { state.value += n; }
      },
      actions: {
        upAsync({ commit }, n) {
          return new Promise(r => setTimeout(() => commit('UP', n), 300));
        }
      },
      getters: {
        doubled: state => state.value * 2
      }
    };
    export default counter;
  • 在 store/index.js 中注册:

    javascript 复制代码
    import Vue from 'vue';
    import Vuex from 'vuex';
    import counter from './modules/counter';
    
    Vue.use(Vuex);
    
    export default new Vuex.Store({
      modules: { counter }
    });
  • 组件内使用(命名空间模块):

    javascript 复制代码
    import { mapState, mapMutations, mapActions, mapGetters } from 'vuex';
    
    export default {
      computed: {
        ...mapState('counter', ['value']),
        ...mapGetters('counter', ['doubled'])
      },
      methods: {
        ...mapMutations('counter', ['UP']),
        ...mapActions('counter', ['upAsync'])
      }
    };
  • 说明:开启命名空间后,访问路径变为 store.state.counter.valuestore.getters['counter/doubled']store.commit('counter/UP')store.dispatch('counter/upAsync');辅助函数通过第二个参数指定命名空间,或在模板中使用带前缀的路径。

​五 实战示例 计数器与异步任务​

  • 目标:实现一个计数器,支持​同步增加​​异步增加​ ,并在页面显示​双倍值​
  • 步骤
    1. 定义模块(store/modules/counter.js,见上节)。

    2. 在组件中使用:

      javascript 复制代码
      <template>
        <div>
          <p>Count: {{ value }}</p>
          <p>Double: {{ doubled }}</p>
          <button @click="localIncrement">+1</button>
          <button @click="localIncrementBy(3)">+3</button>
          <button @click="asyncUp">Async +2</button>
        </div>
      </template>
      
      <script>
      import { mapState, mapGetters, mapMutations, mapActions } from 'vuex';
      
      export default {
        computed: {
          ...mapState('counter', ['value']),
          ...mapGetters('counter', ['doubled'])
        },
        methods: {
          ...mapMutations('counter', ['UP']),
          ...mapActions('counter', ['upAsync']),
          localIncrement() { this.UP(); },
          localIncrementBy(n) { this.UP({ step: n }); }
        }
      };
      </script>
    3. 运行与验证:点击按钮观察 countdoubled 的变化;异步操作完成后状态同步更新。

    4. 小贴士:在 ​严格模式​ 下,仅允许通过 ​Mutation​ 修改状态,有助于捕捉非法直接修改;开发阶段可开启以提升可维护性与可调试性。

相关推荐
by__csdn2 小时前
Node.js版本与npm版本的对应关系
前端·npm·node.js
AI_56782 小时前
Webpack性能优化终极指南:4步实现闪电打包
前端·webpack·性能优化
xuehuayu.cn2 小时前
js es6 class 类中的值是异步赋值, 子类中如何获取这个值?
javascript·es6
威风的虫2 小时前
ES6 数组方法:告别循环,拥抱函数式编程
开发语言·前端·javascript
小杨快跑~3 小时前
ES6 Promise:告别回调地狱的异步编程革命
前端·javascript·ecmascript·es6
linweidong3 小时前
VIVO前端面试题及参考答案
前端·跨域·localstorage·重绘·浏览器兼容·git管理·前端重构
有意义3 小时前
从零搭建:json-server+Bootstrap+OpenAI 全栈 AI 小项目
前端·后端·llm
温宇飞3 小时前
CCState:为大型 Web 应用设计的状态管理库
前端
r0ad3 小时前
读诗的时候我却使用了自己研发的Chrome元素截图插件
前端·javascript·chrome