1.vuex的具体构成关系图
2.vuex的使用
2.1 创建store.js
在使用Vue CLI生成的项目时会让你选择store,选择了后会在页面给你生成一个store.js,这就是最初的store,里面结构如下:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
},
mutations: {
},
actions: {
}
})
复制代码
2.2 state
Vuex的核心就是仓库store,这个store实例会被注入到所有子组件里面,里面的state属性保存着我们的状态,比如我们定义一个状态count:
export default new Vuex.Store({
state: {
count: 10
},
})
复制代码
其他组件想要获取count,需要使用计算属性来获取
export default {
data() {
},
computed: {
count() {
return this.$store.state.count;
}
}
}
复制代码
为根实例中注册 store 选项,该 store 实例会注入到根组件下的所有子组件中,且子组件能通过 this.$store 访问到。通过计算属性,我们就可以在模板里面使用模板语法来调用count了,如下:
<template>
<div>
<p>{{ count }}</p>
</div>
</template>
复制代码
2.3 getter
getter就是对状态进行处理的提取出来的公共部分,当状态要进行筛选这些操作时,我们可以通过getter处理过后再返回给组件使用,比如我们在state部分定义了一个list数组:
export default new Vuex.Store({
state: {
list: [1, 2, 3, 4, 5, 6, 7, 8]
},
});
复制代码
我们想要筛选出数组里面的偶数然后再在组件里面使用,那么筛选的这个工作可以放在getter里面来完成。
export default new Vuex.Store({
state: {
list: [1, 2, 3, 4, 5, 6, 7, 8]
},
getters: { // 这个主要是对状态的处理,相当于把状态处理的方法抽成公共部分来管理了
modifyArr(state) { // 一般化getter
return state.list.filter((item, index, arr) => {
return item % 2 == 0;
})
},
getLength(state, getter) { // 方法里面传getter,调用modifyArr来计算长度
return getter.modifyArr.length;
}
});
复制代码
之后再在其他组件的computed里面去调用getter来获取想要的状态
使用getter的第一种方式:
computed: {
list() {
return this.$store.getters.modifyArr;
},
}
复制代码
使用getter的第二种方式:
his.$store.getters.名称
复制代码
mapGetters
mapGetters 辅助函数仅仅是将 store 中的 getter 映射到局部计算属性,当我们想在组件里面引入多个getter时,可以使用mapGetter:
import {mapGetters} from 'vuex';
复制代码
比如像刚才在在上面定义的modifyArr,getLength。我们想引入这个两个并获取其值:
computed: {
...mapGetter(['modifyArr', 'getLength'])
}
复制代码
你当然可以为其指定别名,不一定非得用store里面getters定义的名字:
computed: {
mapGetter({
arr: 'modifyArr', // 把 `this.arr` 映射为 `this.$store.getters.modifyArr`,下面同理
length: 'getLength'
})
}
复制代码
如果你的computed属性包含其他计算方法,那你就只能使用展开运算符的写法,这里跟mapState有点区别,其他计算属性如果写在mapGetter里面会报错,说不存在的getter,所以用以下的写法:
computed: {
msg() {
return this.num * 10;
},
...mapGetters([
'modifyArr',
'getLength'
])
}
复制代码
或者指定别名
computed: {
msg() {
return this.num * 10;
},
...mapGetters({
getList: 'modifyArr',
length: 'getLength'
})
}
复制代码
复制代码然后再模板里面调用:
<template>
<div>
<h2>mapGetters的使用演示</h2>
<p>你的数字:{{ msg }}</p>
<p>你的数组长度为:{{ length }}</p>
<ul>
<li v-for="(item, index) in getList" :key="index">{{ item }}</li>
</ul>
</div>
</template>
复制代码
2.4 mutation
当我们需要修改store里面的状态时,我们不是在组件里面直接去修改它们,而是通过mutation里面的方法来进行修改,这样有利于追踪状态的改变。 比如state里面有一个count变量,我们点击加减按钮来控制它的值:
mutations: {
add(state) {
state.count++;
},
reduce(state) {
state.count--;
}
},
复制代码
在其他组件里面,我们通过定义methods并绑定事件来触发改变,这里需要使用commit:
methods: {
add() {
this.$store.commit('add');
},
reduce() {
this.$store.commit('reduce');
}
}
复制代码
2.5 action
Action 类似于 mutation,不同在于:
- Action 提交的是 mutation,而不是直接变更状态。
- Action 可以包含任意异步操作。前面说过mutation只能包含同步事务,所以在处理异步事务就需要Action,通过Action控制了异步这一过程,之后再去调用mutation里面的方法来改变状态。
这里我直接贴代码来一目了然,首先我定义了一个状态product:
state: {
product: 'car'
}
复制代码
然后再mutation中定义一个方法:
changeProduct(state, payload) {
state.product = payload.change;
}
复制代码
在action中定义:
actions: {
changeProduct(context, payload) { // 这个context是一个与 store 实例具有相同方法和属性的对象
// 调用mutation里的changeProduct方法
// context.commit('changeProduct', {change: 'ship'});
// 改成异步方式
// setTimeout(() => {
// context.commit('changeProduct', {change: 'ship'});
// }, 1500)
// 使用载荷
let temp = 'ship+' + payload.extraInfo;
setTimeout(() => {
context.commit('changeProduct', {change: temp});
}, 1500)
}
}
复制代码
在组件methods中定义事件触发分发:
methods: {
selectProduct() {
// this.$store.dispatch('changeProduct')
// 载荷方式分发
// this.$store.dispatch('changeProduct', {
// extraInfo: 'sportcar'
// })
// 或者这种
this.$store.dispatch({
type: 'changeProduct',
extraInfo: '->sportcar'
})
}
},
复制代码