Vuex (Vue状态管理器)的学习

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

3、插件

4、热重载

5、严格模式

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值