1、Vuex的基本概念
根据官方文档的解释:Vuex是一个专门为Vue.js应用程序开发的状态管理器模式,集中式的存储管理应用的所有组件状态,并以相应的规则保证状态以一种可预测的方式发生变化。
个人理解:Vuex的应用,可以大大的将本地存储、路由传参解放出来,并且有效避免了不同组件之间的数据传递,极大的提升了开发效率。
2、核心内容
2.1 State(状态的仓库)
Vuex是一个单一的状态树,采用对象包含全部的应用层级状态,Vuex和Vue实例中的data一样遵守相同规则。并且采用Store作为数据仓库,将其挂载在根Vue实例身上,此时就可以全局访问Store的内容了。
2.1.1 定义Store(数据仓库)**
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
const store = new Vuex.Store({
state : {
dataList: [
{title: 'ttx1', index: 1},
{title: 'ttx2', index: 2},
{title: 'ttx3', index: 3}
],
count: 0
}
});
2.1.2 挂载Store在根Vue实例身上**
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex); // 挂在前需要执行该函数
const app = new Vue({
el : '#app',
store,
components: { ...子组件 },
template:'<div>{{ ...本组件内容 }}</div>'
});
2.1.3 访问Vuex中的数据**
import { mapState } from 'vuex';
export default {
......
computed: {
count(){ // 获取Vuex数据第一种用法
return this.$store.state.count;
},
// mapState 是建立与状态管理器中的数据获取功能的语法糖
...mapState({ //第二种用法 采用ES6的扩展运算符
getDataListAr: state => state.dataList;
})
}
};
2.2 Getter(状态的计算属性,可缓存)
先看此例子
computed: {
getDataListSumAr() {
return this.$store.state.dataList.filter(item => item.value)
}
}
在单个组件中使用可以直接这样写,若是其他的多个组件也需要,重复这段代码这样多么违反编程初衷。
2.2.1 Getter的定义
Vue.use(Vuex);
const store = new Vuex.Store({
state : {
dataList: [ 1 , 2, 3 ],
count: 0
},
getters: {
// Getter的第一种用法
getDataListSumAr: state => {
return state.dataList.filter(item => item.value)
},
// Getter可以接受另一个Getter作为参数
getDataListSumLength: (state, getters) => {
return getters.getDataListSumAr.length;
},
// Getter返回一个函数
getDataListItemIndex: state => (title) => {
return state.dataList.filter(item => item.title === title)
},
getCount: state => ++state.count
}
});
2.2.1 Getter的获取调用
computed: {
getDataListSumAr() {
// 通过属性访问会作为Vue响应式的一部分来缓存
return this.$store.getters.getDataListSumAr
},
getDataListItemIndex(title) {
// 通过方法访问则每次都会调用不会缓存
return this.$store.getters.getDataListItemIndex(title);
},
// 类似于mapState只不过访问的是Getter
...mapGetters({
'getDataListSumLength', // 可以直接访问
getPrvCount:'getCount' // 对其重命名后访问
})
}
2.3 Mutation (状态的更改操作)
Vuex中对Store的更改唯一的方法是提交Mutation,Mutation类似于事件方法
2.3.1 定义对Store的更改
Vue.use(Vuex);
const store = new Vuex.Store({
state : {
dataList: [ 1 , 2, 3 ],
count: 0
},
mutations: {
// changeCount是mutation的一个事件类型
changeCount(state, newCount){
state.count = newCount;
},
addCount(state){
state.count++;
}
}
});
2.3.2 对Store的更改以及调用Mutation
// 参数就是对mutation的type进行调用
this.$store.commit('addCount');
// 传参条用,官方叫提交载荷
this.$store.commit('changeCount', 100);
// 参数为对象的调用方式
this.$store.commit({
type: 'changeCount',
data: 200 // 此时会将整个对象作为参数传递,接收时的取值需要去获取data
});
2.3.3 mapMutations映射
import { mapMutation } from 'vuex';
export default {
methods: {
// 映射同上功能相似不在赘述
...mapMutation([
'changeCount'
]),
...mapMutation([
add: 'addCount'
]),
}
}
2.3.4 mutation必须是同步的
在mutation中更改Store的值时,其中不能包含在异步方法内,比如,将更改Store的语句写入异步请求中,组件调用mutation时请求开始,然后组件调用相对应的状态,但是请求没完成,需要更改的状态并没有更新,组件获取的并不是想要的值,这就造成了状态无法追踪。但是我们可以采用Action解决这个需求。
2.3.5 mutation需要遵守的规则
①:务必提前初始化完成需要的状态
②:状态是对象时,更新状态需要采用vue.set()方法,以及采用state.object = { …state.object, newProp: 100 }
2.3.6 mutation可以采用常量代替事件类型
常量事件类型mutation-types.js文件
export const SOME_MUTATION = 'SOME_MUTATION';
import Vuex from 'vuex';
import { SOME_MUTATION } form './mutation-types';
const store = new Vuex.Store({
state: { ...... },
mutations: {
[SOME_MUTATION] (state) => {
......
}
}
});
2.4 Action(异步的状态更改)
Action类似于mutation,但是更优于mutation,在Action内部可以进行异步的操作,并不直接变更状态。
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
addCount(state) {
state.count++
}
},
actions: {
addCount(context) {
context.commit('addCount');
}
}
})
2.4.1 Action的触发
this.$store.dispatch('addCount');
2.4.2 Actions函数的参数
Actions内部函数的参数和Mutations函数内部的参数是不一样的,其内部的context(理解为上下文)对象,包含了state、commit(可在Module中理解)。
解构用法:
const store = new Vuex.Store({
state: {
data: []
},
mutations: {
changeData(state, data) {
state.data = data;
},
},
actions: {
addCount({ state, commit }, data) {
commit('changeData', [...state.data, data]);
}
}
})
详细参数:
context: {
state, //同store.state,在模块中则为局部状态
rootState, //同store.state,一般在模块中使用,获取根节点的状态
commit, //同store.commit
dispatch, //同store.dispatch
getters //同store.getters
}
2.4.3 Actions的分发mapActions
Actions的定义:
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
addCount(state){
state.count++
},
changeCount(state, numbers){
state.count = numbers;
}
},
actions: {
addCount({state, commit}){
commit('addCount');
},
changeCount({state, commit}, numbers){
commit('changeCount', number);
}
}
});
Action的分发,使用mapActions映射在组件中
import { mapActions } from 'vuex';
export default {
methods: {
...mapActions([
'changeCount'
]),
...mapActions({
add: 'addCount'
})
}
}
2.4.4 Actions的异步用法
Action实际是为了异步而设定的,以上的用法是同步用法,展示其基本使用,下面的例子是正式的异步用法。
用法一:返回Promise对象,可以在组件中接收回调函数。
const store = new Vuex.Store({
......
actions:{
response({ commit }){
return new Promise((resolve, reject) => {
axios(....).then( data => {
commit('....', data);
resolve();
} );
})
}
}
});
用法二:采用async/await组合Action
actions: {
async responseA({commit}){
commit('changeCount', await getNumbers());
},
async responseB({commit, dispatch}){
await dispatch('responseA');
commit('...', await someOther())
}
}
2.5 Module(模块化)
2.5.1 Module基本概念
在状态管理器中,状态的记录都是由Store单独记录,但是这种单独记录在状态较少的情况下还可以胜任,若是大量的状态都在一个Store中,这带来的麻烦是不可想象的, 所以引入了Module分模块的管理状态,让状态从单一状态树分割成不同的模块。
2.5.2 Module的基本用法
用法一:
const StoreA = {
state: {},
mutations: {},
actions: {}
}
const StoreB = {
state: {},
mutations: {},
actions: {}
}
const Store = new Vuex.Store({
modules: {
A: StoreA,
B: StoreB
}
});
//可以通过Store.state.A 和 Store.state.B调用
用法二:
const Store = new Vuex.Store({
state: {...},
mutations: {},
actions: {},
modules: {
first: {
state:{},
mutations:{}
......
},
second: {
state: {},
mutations: {},
......
},
......
}
});
2.5.3 Module内的局部参数
注意一: 对于在Module内的Mutation以及Getter操作,Module会将局部的state作为他们的第一个参数.
注意二: 对于Action,其参数context,若在Module中,context.state是局部的,同时context.rootState为根节点的state。
注意三: 对于Getter,根节点rootState会作为第三个参数传递。
const Store = new Vuex.Store({
state: {},
mutations: {},
modules: {
first: {
state: {...},
mutations: {
// 此state为当前的局部state
someThing(state){
...
}
},
// 局部的state、getters以及根节点state
getters: {
someThing(state, getters, rootState) {
...
}
},
//
actions: {
someThing({ state, commit, rootState }){
...
}
}
}
}
});
未完待续…
2.5.4 命名空间
namespaced:true