通过vuex的一个小demo(todos),分析所需要掌握的知识点;
1、为何使用Vuex
使用Vue开发的过程中,我们经常会遇到一个状态可能会在多个组件之间使用,这样vuex中有一个核心仓库store可以来存储这个状态,其他组件就可以共同访问此状态。
1.1 Vuex原理解析图
- 在没有actions的情况下:
- 数据:state –> data
- 获取数据:getters –> computed
- 更改数据:mutations –> methods
视图通过点击事件,触发mutations中方法,可以更改state中的数据,一旦state数据发生更改,getters把数据反映到视图。那么actions,可以理解处理异步,而单纯多加的一层。
- 既然提到了mutions ,actions这时候 就不得不提commit,dispatch这两个有什么作用呢?
- 在vue例子中,通过click事件,触发methods中的方法。
- 当存在异步时,而在vuex中需要dispatch来触发actions中的方法,actions中的commit可以触发mutations中的方法。
- 当存在同步时,则直接在组件中commit触发vuex中mutations中的方法。
2、初步使用Vuex
-
2.1 store仓库
Vuex的核心就是仓库store,这个store实例会被注入到所有子组件里面。创建项目时会选择store,store下的index.js代码:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
},
mutations: {
},
actions: {
}
})
复制代码
-
2.2 State
store里面的state属性保存着我们所需要的状态。
export default new Vuex.Store({
state: {
key:'all'
},
})
复制代码
上述代码是在store/index.js中;
那 组件 如何取到这个key呢,可以计算属性来获得:
export default {
data() {
},
computed: {
key() {
return this.$store.state.count;
}
}
}
复制代码
因为根实例中注册 store 选项,该 store 实例会注入到根组件下的所有子组件中,且子组件能通过 this.$store 访问到。通过计算属性,我们就可以在模板里面使用模板语法来调用key了,如下:
<template>
<div>
<p>{{ key }}</p>
</div>
</template>
复制代码
-
2.2.1 mapState
获取key值的时候,要调用计算属性computed,但有时候需要获取多个状态,但是使用计算属性会调用多次,显得麻烦,这里借助mapState方法来获取state里边的状态 , 如:在组件中获取key
使用mapState需要在组件中引入
import { mapState } from 'vuex'
export default {
data() {
},
computed: {
...mapState(['key'])
}
}
复制代码
这样写既方便又省事,避免重复代码,就可以把key从store中拿过来,应用到模板中;
-
2.3 Mutations
当我们需要修改store里面的状态时,我们不是在组件里面直接去修改它们,而是通过mutation里面的方法来进行修改,这样有利于追踪状态的改变。如:改变key值
mutations:{
changeKey(state,newKey) {
state.viewKey = newKey
}
复制代码
在其他组件里面,我们通过定义methods并绑定时间来触发改变,这里需要使用commit:
methods:{
changeViewKey() {
this.$store.commit('changeKey','ccc') //里边可以传入相应所需的参数,需要传递多个参数时,可以封装成一个对象,将这个对象传递过去
}
}
复制代码
-
2.3.1 mapMutations
这个跟前面的那几个函数一个道理,都是为了简化调用,使用方法如下:
import { mapMutations } from 'vuex'
export default {
data() {
},
methods: {
//将 `this.changeViewKey()` 映射`this.$store.commit('changeKey')`
...mapMutations({changeViewKey:'changeKey'})
}
}
复制代码
-
2.4 Action
Action 类似于 mutation,不同在于:
Action 提交的是 mutation,而不是直接变更状态。
Action 可以包含任意异步操作。
前面说过mutation只能包含同步事务,所以在处理异步事务就需要Action,通过Action控制了异步这一过程,之后再去调用mutation里面的方法来改变状态。
state:{
list:[]
}
复制代码
在mutations中定义一个方法
init(state,data){
state.list=data
}
复制代码
在action中定义:
actions:{
//这个context是一个与 store 实例具有相同方法和属性的对象
getList(context) {
//异步请求数据
axios.get('url').then(({ data }) => {
// 调用mutations中的initList方法
context.commit('initList', data)
})
}
复制代码
这样就将请求到的data数据,赋值给了state中的list数组
我们想在组件中使用list 数组,就先在created中触发actions,再利用…mapState[‘list’] 在模板中使用
created() {
this.$store.dispatch('getList')
},
复制代码
-
2.4.1 mapActions
import {mapActions} from 'vuex';
export default {
// ...
methods: {
...mapActions([
'increment', // 将 `this.increment()` 映射为 `this.$store.dispatch('increment')`
// `mapActions` 也支持载荷:
'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.dispatch('incrementBy', amount)`
]),
...mapActions({
add: 'increment' // 将 `this.add()` 映射为 `this.$store.dispatch('increment')`
})
}
}
复制代码
-
2.5 Getters
getter就是对状态进行处理的提取出来的公共部分,当状态要进行筛选这些操作时,我们可以通过getter处理过后再返回给组件使用,它不会改变原数组的信息而是返回一个新的数组,比如我们在state部分定义了一个list数组:
export default new Vuex.Store({
state: {
list: [1, 2, 3, 4, 5, 6, 7, 8]
},
});
复制代码
我们想要筛选出数组里面的偶数然后再在组件里面使用,那么筛选的这个工作可以放在getter里面来完成。
getters:{
// 这个主要是对状态的处理,相当于把状态处理的方法抽成公共部分来管理了
oushuArr(state){
return state.list.filter((item) => {
return item % 2 == 0
})
},
// 方法里面传getter,调用oushuArr来计算长度
getLength(state, getter) {
return getter.oushuArr.length;
}
}
复制代码
之后再在其他组件的computed里面去调用getter来获取想要的状态
computed: {
list() {
return this.$store.getters.oushuArr;
},
length(){
return this.$store.getters.getLength;
}
}
复制代码
-
2.5.1 mapGetters
mapGetters 辅助函数仅仅是将 store 中的 getter 映射到局部计算属性,当我们想在组件里面引入多个getter时,可以使用mapGetter:
import {mapGetters} from 'vuex';
export default {
computed: {
...mapGetter(['oushuArr', 'getLength'])
//还可以为其增加别名
//...mapGetter({Arr:'oushuArr', length:'getLength'})
}
}
复制代码
在模板里面调用使用:
<template>
<div>
<h2>mapGetters的使用演示</h2>
<p>你的数组长度为:{{ getLength }}</p>
<ul>
<li v-for="(item, index) in oushuArr" :key="index">{{ item }}</li>
</ul>
</div>
</template>
复制代码