Vuex 是 Vue.js 的状态管理工具,适用于多个组件共享数据的情况。可以理解为:“一个全局的数据仓库”,所有组件都可以从这里取数据或者改数据,而不用层层传值。
1. Vuex 的 5 个核心概念
名称 | 作用 | 例子 |
---|---|---|
state | 存储数据 | state.count = 0 |
getters | 计算属性 | getters.doubleCount -> state.count * 2 |
mutations | 同步 修改数据 | mutation: state.count++ |
actions | 异步 修改数据 | action: setTimeout(() => commit('increment'), 1000) |
modules | 拆分模块 | modules: { user, cart } |
2. 代码示例
(1) 安装 Vuex
Vue 2
npm install vuex@3
Vue 3
npm install vuex@4
(2) 创建 Vuex 仓库
创建 store/index.js
:
import Vue from 'vue'; // Vue 2
import Vuex from 'vuex';
Vue.use(Vuex);
export default new Vuex.Store({
state: {
count: 0
},
mutations: {
increment(state) {
state.count++;
}
},
actions: {
asyncIncrement({ commit }) {
setTimeout(() => {
commit('increment');
}, 1000);
}
},
getters: {
doubleCount: state => state.count * 2
}
});
(3) 在 main.js
引入 Vuex
import Vue from 'vue';
import store from './store';
new Vue({
store, // 挂载 Vuex
render: h => h(App)
}).$mount('#app');
(4) 在组件中使用 Vuex
在 Counter.vue
组件:
<template>
<div>
<p>当前计数:{{ count }}</p>
<p>两倍计数:{{ doubleCount }}</p>
<button @click="increment">加 1</button>
<button @click="asyncIncrement">1 秒后加 1</button>
</div>
</template>
<script>
import { mapState, mapMutations, mapActions, mapGetters } from 'vuex';
export default {
computed: {
...mapState(['count']), // 映射 state.count
...mapGetters(['doubleCount']) // 映射 getters
},
methods: {
...mapMutations(['increment']), // 直接调用 mutation
...mapActions(['asyncIncrement']) // 调用 action
}
};
</script>
3. Vuex 的工作流程
- state 存数据(全局)
- 组件 mapState 取数据
- 组件 mapMutations 调用 mutation 同步修改数据
- 组件 mapActions 调用 action 异步修改数据
- getters 计算属性,自动计算
4. 进阶:Vuex 的 modules
(模块化)
如果项目很大,可以把 Vuex 拆成多个模块。
创建 store/modules/user.js
:
export default {
state: {
name: '张三'
},
mutations: {
setName(state, newName) {
state.name = newName;
}
},
actions: {
asyncChangeName({ commit }) {
setTimeout(() => {
commit('setName', '李四');
}, 1000);
}
},
getters: {
upperName: state => state.name.toUpperCase()
}
};
然后,在 store/index.js
注册:
import Vue from 'vue';
import Vuex from 'vuex';
import user from './modules/user';
Vue.use(Vuex);
export default new Vuex.Store({
modules: {
user
}
});
组件中使用:
<template>
<div>
<p>用户名:{{ name }}</p>
<p>大写用户名:{{ upperName }}</p>
<button @click="setName('王五')">改名</button>
<button @click="asyncChangeName">1 秒后改名</button>
</div>
</template>
<script>
import { mapState, mapMutations, mapActions, mapGetters } from 'vuex';
export default {
computed: {
...mapState('user', ['name']),
...mapGetters('user', ['upperName'])
},
methods: {
...mapMutations('user', ['setName']),
...mapActions('user', ['asyncChangeName'])
}
};
</script>
5. Vuex 与 Pinia
Vuex 在 Vue 3 之后,官方推荐使用 Pinia 替代 Vuex:
- Vuex 代码复杂,需要
mutations
、actions
等 - Pinia 更简单,直接
state + actions
- Pinia 支持 TypeScript
如果你的项目是 Vue 3,可以考虑使用 Pinia,使用方式类似 Vuex。