vuex
大约 3 分钟
vuex
在前面我们讲了组件间的通信,最主要的都是子传父,父传子。
vuex可以把所有的数据都存在一个公用的容器里面,所有组件都可以使用这个容器中的数据。
vuex也叫状态管理模式,数据也叫做状态
- state:存储store的各种状态
- mutation: 通过更改状态,改变store的状态只能通过mutation方法
- action: 异步更改状态
- module: 模块化
- getter: 相当于计算属性,计算出一些新的状态值

import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex) // 默认会执行当前插件的install方法
// 通过Vue中的一个属性Store创建一个store的实例
// 在vue的初始化过程中, 注入了一个store属性,内部会将这个属性放到每个组件的$store上
export default new Vuex.Store({
state: { // 单一数据源
age: 10
},
getters: { // 类似于计算属性
myAge(state) { // 使用状态计算出一个新的状态
return state.age + 20
}
},
mutations: { // 同步更改状态
changeAge(state, age) { // 修改状态的方法,同步的修改
state.age = age
}
},
actions: {
changeAgeAsync({commit}, age) {
setTimeout(() => {
commit('changeAge', age)
}, 1000)
}
},
modules: {
}
})
<template>
<div id="app">
{{$store.state.age}}
<button @click="changeState">更改数据</button>
<button @click="changeStateAsync">异步更改</button>
<div>我的年龄:{{$store.getters.myAge}}</div>
<hello></hello>
</div>
</template>
<script>
import Hello from './components/hello.vue'
export default {
components: {
Hello
},
methods: {
changeState() {
this.$store.commit('changeAge', 100)
},
changeStateAsync() {
this.$store.dispatch('changeAgeAsync', 50)
}
},
}
</script>
<style lang="less">
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
}
#nav {
padding: 30px;
a {
font-weight: bold;
color: #2c3e50;
&.router-link-exact-active {
color: #42b983;
}
}
}
</style>
vuex辅助函数
mapState
state的辅助函数需要映射到计算属性中computed,映射的名称一定要相同,然后就可以通过this访问到state。
export default { name: 'Hello', computed: { ...mapState(['age']) } } <div> 通过辅助函数: <div>{{age}}</div> </div>
mapMutations
mutation的辅助函数mapMutations把mutations里面的方法映射到methods中。映射的名称一定要相同,然后就可以通过this调用mutaition的方法。
<button @click="changeAgeMapMutation"> 通过辅助函数mapMutations更改数据 </button> methods: { ...mapMutations(['changeAge']), changeAgeMapMutation() { this.changeAge(300) } }
mapActions
mapAcions:把actions里面的方法映射到methods中
<button @click="changeAgemapActions"> 通过辅助函数mapActions异步更改数据 </button> methods: { ...mapActions(['changeAgeAsync']), changeAgemapActions() { this.changeAgeAsync(700) } }
mapGetters
mapGetters:把getters属性映射到computed身上
module
Vuex 允许我们将 store 分割成大大小小的对象,每个对象也都拥有自己的 state、getter、mutation、action,这个对象我们把它叫做 module(模块),在模块中还可以继续嵌套子模块、子子模块 ……
命名空间
如果模块不使用命名空间的话,默认情况下模块内部的 getter, action 和 mutation是注册在全局全局命名空间的
想要让模块内部的 getter, mutation , action只作用域当前局部模块内的话可以给模块添加namespaced属性:
export default {
namespaced:true,
stateB: { // 单一数据源
ageB: 10
},
getters: { // 类似于计算属性
myAge(state) { // 使用状态计算出一个新的状态
return state.ageB + 20
}
},
mutations: { // 同步更改状态
changeAge(state, age) { // 修改状态的方法,同步的修改
console.log('moduleB---changeAge')
state.ageB = age
}
},
actions: {
changeAgeAsync({commit}, age) {
console.log('moduleB---changeAgeAsync')
setTimeout(() => {
commit('changeAge', age)
}, 1000)
}
},
modules: {
}
}
当开启命名空间的模块被注册后它的所有 getter、action 及 mutation 都会自动根据模块注册的路径调整命名,所以触发路径也有所改变:
...mapState({
moduleAage: state => state.moduleA.ageA
}),
...mapMutations({
changeAge: 'moduleA/changeAge',
changeAgeB: 'moduleB/changeAge'
}),
changeAgeMapMutation() {
this.changeAge(300)
// this.$store.commit('moduleA/changeAge', 500)
},