[Vuex] Detailed explanation of vue state machine

Table of contents

Vuex

1. Five attributes of Vuex

2. Working principle of Vuex

3. Use of Vuex

In the html file use

helper function

Modular modules and namespaced

Use in vue-cli scaffolding


Vuex

Vuex is a state management pattern developed specifically for Vue.js applications . It uses a centralized storage to manage the state of all components of the application, and uses corresponding rules to ensure that the state changes in a predictable manner.

Vuex is a state management mode, also called a state machine, which puts the data shared by components into the state machine for unified management. If a component wants to get data, it can get it from its own data model or from the warehouse. Vuex can be understood as a warehouse.

Suppose component A wants to get the data in component B, then put the data of component A and component B into Vuex, component A wants to get the data of component B from vuex, and component B wants to get the data of component A Take it from Vuex.

1. Five attributes of Vuex

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

2. Working principle of Vuex

Three main attributes of vuex: state, mutations, actions


 

When we declare a state machine and inject it into the Vue instance, there will be a $store attribute on the Vue instance, which has methods such as dispatch and commit. 

Analyze the above picture:

The Vue component dispatches the method that needs to be executed to Actions for execution through the dispatch method, but Actions will not execute the method, so it submits the method to Mutation for execution through the commit method. After the Mutation is executed, the processed data is sent to State , and then State re-renders the data to the page.

Note: When the data that the Vue component needs to operate does not need to be obtained through network requests, actions can be skipped and directly submitted to mutations for processing using the commit method.

3. Use of Vuex

In the html file use

1. Import Vuex through CDN

Vuex is a plug-in of Vue, which needs to be installed when using it

<script src="https://cdnjs.cloudflare.com/ajax/libs/vuex/3.6.0/vuex.min.js" integrity="sha512-uN93RUcJ9frHH6dyLknjgalFe7JNkfb3OjW4Qgg5xjaVA3U7l0diZ3hGL2Puk/38sp7xD/SLHdNFit7Kq3RbtQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

2. Declare the state machine

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

3. Inject the state machine into the Vue instance

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

At this point, you can print the $store in the Vue instance to have a look:

console.log(vm.$store)

 So we can use $store.state.xxx and $store.getters.xxx in the interpolation syntax to access the data in the state and the methods in the getters.

example:

<!DOCTYPE html>
<html lang="en">

<head>
	<meta charset="UTF-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Document</title>
	<script src="https://cdn.jsdelivr.net/npm/[email protected]"></script>
	<!-- 1、引入Vuex -->
	<script src="https://cdnjs.cloudflare.com/ajax/libs/vuex/3.6.0/vuex.min.js" integrity="sha512-uN93RUcJ9frHH6dyLknjgalFe7JNkfb3OjW4Qgg5xjaVA3U7l0diZ3hGL2Puk/38sp7xD/SLHdNFit7Kq3RbtQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
</head>

<body>
	<div id="app">
		<!-- 使用state中的数据和getter中的方法 -->
		{
   
   {$store.state.msg}}
		{
   
   {$store.getters.MSG}}
		<hr>
		{
   
   {$store.state.sum}}
		<button @click="foo">点击加{
   
   {n}}</button>
	</div>
    <script>
	  let store = new Vuex.Store({
		state: {
			msg: 'hello',
			sum: 0
		},
		// getters用来处理state中的数据
		getters: {
			MSG(state){ //默认有一个参数,它是一个对象,里面存放了state中的数据
				// console.log(state);
				return state.msg.toUpperCase()
			}
		},
		actions: {
			// 默认有两个参数:sto是一个类状态机对象; value是dispatch传递过来的数据
			add(sto, value){
				// console.log(sto, value, 'actions');
				// 提交突变给mutations
				// commit('mutations中的方法名', 需要传递的数据)
				sto.commit('ADD', value)
			}
		},
		mutations: {
			// 最终在mutations中处理数据
			// 默认两个参数:state是一个对象,里面存放了state中的数据; value是commit提交的时候传递过来的数据
			ADD(state, value){
				// console.log(state, value, 'mutations');
				state.sum += value
			}
		},
	})

	let vm = new Vue({
		store,
		el: "#app",
		data: {
			n: 2
		},
		methods:{
			foo(){
				// 派发一个动作给actions
				// dispatch('actions中的方法名', 需要传递的数据)
				this.$store.dispatch('add', this.n)
			}
		}
	})
	// console.log(vm); //打印Vue实例,可以看到Vue实例上有一个$store属性
  </script>
</body>

</html>

helper function

The component auxiliary functions provided by Vuex include mapState, mapGetters, mapActions, and mapMutations. They exist on the Vuex object and can be called using Vuex.mapState, or they can be deconstructed from Vuex for use:

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

1. The mapState method: used to help map the data in the state to a computed property

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方法
},

After using the mapState method, we can directly use { {msg}}, { {sum}} in the interpolation syntax, instead of writing: { {$store.state.msg}}, { {$store.state.sum} }, and the same is true for the mapGetters method.

2. mapGetters method: used to help map the data in getters to computed properties

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

3. mapActions method: the method used to help generate dialogue with actions, that is, the function containing $store.dispatch(xxx)

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

4. mapMutations method: a method used to help generate dialogues with mutations, that is, a function containing $store.commit(xxx)

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

Note: When using mapActions and mapMutations, if parameters need to be passed, the parameters must be passed when the template is bound to the event.

<button @click="foo(n)">点击加{
   
   {n}}</button>

Modular modules and namespaced

Due to the use of a single state tree, all the state of the application will be concentrated into a relatively large object. When the application becomes very complex, the store object can become quite bloated. In order to solve the above problems, Vuex allows us to divide the store into modules, each module has its own state, mutation, action, getter, and even nested submodules. namespaced means to set the namespace.

The modules attribute in Vuex is used to store the state machine of each module.

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) Read the data in the state in the component 

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

 (2) Read the data in the getters in the component

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

(3) Call dispatch in the component

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

(4) Call commit in the component

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

Use in vue-cli scaffolding

Write a small case: when we click to log in, we will get a token value, which is also used by other components, so we can store the token value in vuex for use by all components.

1. Install vuex

Note: vuex4 and above can only be used in vue3, vue2 uses vuex3 version, if you do not specify the version during installation, the latest version of vuex will be installed

npm i [email protected]

2. Create a new folder store under src, and then create a new folder login under the store folder to store login-related state machines

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. Create a new folder pages under src to store components

login.vue

<template>
	<div>
		登录页面-----
		<button @click='login(obj)'>登录</button>
	</div>
</template>
<script>
import {mapActions} from 'vuex'
export default {
	data(){
		return {
			obj:{
				username:"xxx",
				password:xxx
			}
		}
	},
	methods:{
		// 分发状态机动作 发送登录请求
		...mapActions('login',['login'])
	}
}
</script>

 user.vue

<template>
	<div>
		用户页面--{
   
   {token}}
	</div>
</template>
<script>
import {mapState} from 'vuex';
export default {
	data(){
		return {}
	},
	computed:{
		...mapState('login',['token'])
	}
}
</script>

 

Guess you like

Origin blog.csdn.net/lq313131/article/details/127131901