【Vuex】vue状态机详解

目录

Vuex

1、Vuex的五个属性

2、Vuex工作原理

3、Vuex的使用

在html文件中使用

辅助函数

模块化modules和命名空间namespaced

在vue-cli脚手架中使用


Vuex

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。

Vuex是一个状态管理模式,也叫状态机,将组件共享的数据放到状态机中统一管理,组件想拿数据可以从自己的数据模型中拿,也可以从仓库中拿,可以把vuex理解成一个仓库。

假设A组件想要拿B组件里面的数据,那就把A组件和B组件的数据放到Vuex中,A组件想要获取B组件数据从vuex中拿,B组件想要获取A组件的数据也从Vuex拿。

1、Vuex的五个属性

{
	//state 维护的是公共状态(数据),类似Vue中的data
	state: {},
	//getters 处理state中的数据并返回新数据,类似计算属性computed
	getters: {},
	//mutations 突变,修改state的唯一方式,只能做同步操作
	mutations: {},
	//actions 动作,处理异步操作,获取后台响应,提交数据给突变mutations
	actions: {},
	// 状态机可以有多个,modules用来存放各模块的状态机
	modules: {}
}

2、Vuex工作原理

vuex三个主要的属性:state、mutations、actions

【Vuex】vue状态机详解_第1张图片
 

当我们声明了一个状态机并将其注入Vue实例中,那么Vue实例上就会存在一个$store属性,该属性上有dispatch和commit等方法。 

分析上图:

Vue组件将需要执行的方法通过dispatch方法派发给Actions执行,但是Actions不会去执行该方法,于是它又通过commit方法提交该方法给Mutation来执行,Mutation执行完后,将处理完的数据给State,然后State重新渲染数据到页面。

注意:当Vue组件需要操作的数据不需要通过网络请求得到时,可以跳过actions,直接使用commit方法提交给mutations处理。

3、Vuex的使用

在html文件中使用

1、通过CDN引入Vuex

Vuex是Vue的一个插件,使用时需要安装


2、声明状态机

let store = new Vuex.Store(
	{
		//state 维护的是公共状态,类似Vue中的data
		state: {},
		//getters 处理state中的数据并返回新数据,类似计算属性computed
		getters: {},
		//mutations 突变,修改state的唯一方式,只能做同步操作
		mutations: {},
		//actions 动作,处理异步操作,获取后台响应,提交数据给突变mutations
		actions: {}
	}
)

3、将状态机注入Vue实例

let vm = new Vue({
	// 将状态机注入Vue实例
	store,
	el: "#app",
	data: {}
})

此时可以打印Vue实例中的$store看一下:

console.log(vm.$store)

【Vuex】vue状态机详解_第2张图片

 因此我们可以在插值语法中使用 $store.state.xxx 和 $store.getters.xxx 访问state中的数据和getters中的方法。

例子:





	
	
	
	Document
	
	
	



	
{{$store.state.msg}} {{$store.getters.MSG}}
{{$store.state.sum}}

【Vuex】vue状态机详解_第3张图片

辅助函数

Vuex提供的组件辅助函数有mapState、mapGetters、mapActions、mapMutations,它们存在Vuex对象上,使用时可以使用Vuex.mapState的方式调用,也可以将它们从Vuex中解构出来使用:

let { mapState, mapGetters, mapActions, mapMutations } = Vuex

1、mapState方法:用于帮助映射 state 中的数据为计算属性

computed:{
	// msg(){
	// 	return this.$store.state.msg
	// },
	// sum(){
	// 	return this.$store.state.sum
	// }
	//-----------------------------------------------------
	// 借助mapState函数生成上述计算属性
	// mapState返回一个对象,我们需要使用扩展运算符将它们展开
	// 1、对象写法
	...mapState({msg:'msg',sum:'sum'})
	// 2、数组写法
	...mapState(['msg','sum'])
},
// 测试,看一下mapState返回值
created(){
	let a = mapState({msg:'msg',sum:'sum'})
	console.log(a); //返回一个对象,对象中有msg、sum方法
},

使用了mapState方法之后,我们在插值语法直接使用{{msg}}、{{sum}}即可,不需要写成:{{$store.state.msg}}、{{$store.state.sum}},同理mapGetters方法也一样。

2、mapGetters方法:用于帮助映射 getters 中的数据为计算属性

computed:{
	// MSG(){
	// 	return this.$store.getters.MSG
	// }
	//------------------------------------------------------
	// 借助mapGetters函数生成上述计算属性
	// 1、对象写法
	...mapGetters({MSG:'MSG'})
	// 2、数组写法
	...mapGetters(['MSG'])
},

3、mapActions方法:用于帮助生成与 actions 对话的方法,即包含$store.dispatch(xxx)的函数

methods:{
	// foo(){
	// 	this.$store.dispatch('add', this.n)
	// }
	//--------------------------------------------
	// 借助mapActions函数生成上述foo方法
	// mapActions返回一个对象,我们需要使用扩展运算符将它们展开
	// 1、对象写法
	...mapActions({foo:'add'}),
	// 2、数组写法   (注意:需要对象的属性名和属性值一样才能写成下面的数组形式)
	...mapActions(['foo'])
}

4、mapMutations方法:用于帮助生成与 mutations 对话的方法,即包含$store.commit(xxx)的函数

methods:{
	// foo(){
	// 	this.$store.commit('ADD', this.n)
	// }
	//--------------------------------------------
	// 借助mapMutations函数生成上述foo方法
	// mapMutations返回一个对象,我们需要使用扩展运算符将它们展开
	// 1、对象写法
	...mapMutations({foo:'ADD'}),
	// 2、数组写法   (注意:需要对象的属性名和属性值一样才能写成下面的数组形式)
	...mapMutations(['foo'])
	
}

注意:使用 mapActions 和 mapMutations 时,若需要传递参数,那么参数要在模板绑定事件的时候传参。

模块化modules和命名空间namespaced

由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。为了解决以上问题,Vuex 允许我们将 store 分割成模块,每个模块拥有自己的 state、mutation、action、getter,甚至是嵌套子模块。namespaced表示设置命名空间。

Vuex中的modules属性用来存放各个模块的状态机。

let aModule = {
	// 开启命名空间
	namespaced: true,
	state:{},
	getters:{},
	actions:{},
	mutations:{}
}
let bModule = {
	namespaced: true,
	state:{},
	getters:{},
	actions:{},
	mutations:{}
}
let store = new Vuex.Store({
	modules:{
		a:aModule,
		b:bModules
	}
})

(1)组件中读取state中数据 

// 方式一:自己读取
this.$store.state.a.xxx
// 方式二:使用mapState读取  表示后面数组里面的属性是a模块的
...mapState('a',['xxx1','xxx2','xxx3'])

 (2)组件中读取getters中的数据

// 方式一:自己读取
this.$store.getters['a/xxx']
// 方式二:使用mapGetters读取  表示后面数组里面的属性是a模块的
...mapGetters('a',['xxx1','xxx2','xxx3'])

(3)组件中调用dispatch

// 方式一:自己直接dispatch
this.$store.dispatch('a/xxx',需要传递的数据)
// 方式二:使用mapActions读取
...mapActions('a',['xxx1','xxx2','xxx3'])

(4)组件中调用commit

// 方式一:自己直接commit
this.$store.commit('a/xxx',需要传递的数据)
// 方式二:使用mapMutations读取
...mapMutations('a',['xxx1','xxx2','xxx3'])

在vue-cli脚手架中使用

写个小案例:当我们点击登录的时候会获取到一个token值,这个token值其他组件也需要使用,因此我们可以把token值存在vuex中,供所有的组件使用。

1、安装vuex

注意:vuex4版本以上只能在vue3中使用,vue2使用vuex3版本,安装时如果不指定版本,会安装最新版本的vuex

npm i [email protected]

2、在src下新建一个文件夹store,然后在store文件夹下再新建一个文件夹login,存放登录相关的状态机

【Vuex】vue状态机详解_第4张图片

src/store/index.js 

import Vue from 'vue';
import Vuex from 'vuex';
// 引入登录状态机
import login from '../store/login/login';

Vue.use(Vuex);

export default new Vuex.Store({
	state:{},
	getters:{},
	mutations:{},
	actions:{},
	modules:{
		login
	}
})

src/login/login.js

import axios from 'axios';
// 这是我登录状态机配置对象
export default {
	// 开启命名空间
	namespaced: true,
	state: {
		token: localStorage.getItem('token') || ""
	},
	gettes: {},
	mutations: {
		SET_TOKEN(state, payload) {
			state.token = payload;
			// 持久化储存 
			localStorage.setItem('token', payload)
		}
	},
	actions: {
		async login({commit}, payload) {
			// 发送异步请求
			let res = await axios.post('登录接口地址', payload)
			// console.log(res);
			commit('SET_TOKEN', res.data.data.token)
		}
	}
}

3、在src下新建文件夹pages,存放组件

login.vue


 user.vue


 【Vuex】vue状态机详解_第5张图片

你可能感兴趣的:(vue,vue.js,javascript,Vuex)