1. Vuex插件

1.1 什么是Vuex?


概念:专门在Vue中实现集中式状态(数据)管理的一个Vue的插件。

  • 与集中式对应的就是分布式。
  • 对vue应用中多个组件的共享撞他进行集中式的管理(读/写),也是一种组件间通信的方式,且适用于任意组件间的通信。

1.2 为什么要用Vuex?


全局事件总线的一个对组件数据的读写效果:
在这里插入图片描述
实现读,需要一对$emit ,$on ;同样需要些也是需要一对$emit ,$on。如果多个组件都要对数据进行读写操作,那样用全局事件总线来解决这个问题就太麻烦了!!


Vuex就弥补了上面的问题:
在这里插入图片描述


什么时候使用Vuex?

  • 多个组件的共享状态(数据)的读写操作。

1.3 Vuex的原理图


Vuex的相关结构:

  • Actions(行动):看似是一个传递效果,其实它可以发送ajax请求,拿到接口相关的数据的。
  • Mutations(转变,修改):负责修改State状态,也就是数据。
  • State(状态 ):状态 , 在这里本质就是数据对象。
  • 上面三个本质都是对象,Actions对象,Mutations对象。State对象。

在这里插入图片描述

上面各个函数很重要,像dispatch函数和commit函数都是开发人员自己直接可以调用的;而mutate和render是vue自主调用的函数。


Vuex中的Actions是可以跳过的:
在这里插入图片描述


Vuex的store,store是Actions,Mutations,State三个对象的管理者。

  • 像store.dispatch和store.commit都是调用store身上的方法。
    在这里插入图片描述

2. 搭建Vuex环境

2.1 安装Vuex的注意事项


在2022年2月7日,vue3成为了默认版本。

也就是说我们现在执行npm i vue命令 , 安装的直接就是vue3了。

  • vue3成为了默认版本的同时,vuex也更新到了4版本。4版本的vuex只能适用于vue3。
  • 再安装npm i vuex , 安装的就是vuex4版本。
  • 因此,对于vue2项目,我们不能直接执行npm i vuex,因为,4版本的vuex不适用于vue2。如下图错误:
    在这里插入图片描述

简而言之就是,vue2要用vuex的3版本。vue3要用vuex的4版本。

  • 所以对于vue2版本,执行npm i vuex@3 严格指定版本号!

2.2 搭建Vuex环境


第一步:执行npm i vuex@3 命令(这里我们使用的vue2版本项目)。

在这里插入图片描述


第二步:Vue.use(Vuex) 引入vuex插件。
在这里插入图片描述

一旦使用了Vuex的插件,我们就可以在vm实例对象或者vc实例对象上面,添加一个store配置项。

之后,我们都是通过store配置项来操作。


第三步:创建文件src/store/index.js(官方推荐) , 也有src/vuex/store.js。见到store就必须知道!
在这里插入图片描述


第四步:修改index.js文件。

// 该文件用于创建Vuex中最为核心的store

//引入Vue,使用插件
import Vue from 'vue'
//引入Vuex
import Vuex from 'vuex'

//引入Vuex的插件
//在这里使用use,就是为了防止出现一个before的错误。该错误见2.3 Vue的注意事项
Vue.use(Vuex)

// 准备actions 用于响应组件中的动作
const actions  = {
}

// 准备mutations 用于操作数据(state状态)
const mutations = {
}

// 准备state 用于存储数据
const state = {
}

//创建store
const store = new Vuex.Store({
	// actions:actions,
	// mutations:mutations,
	// state:state,
	//简写为一下形式:
	actions,
	mutations,
	state,
})

//对于当前文件我们要让外部文件使用,就必须要暴露相关信息。
//暴露store
export default store
//这样外部import导入的使用拿到的就是store这个对象

第五步:修改main.js导入我们设置的src/store/index.js文件。这样就可以在vm或者vc实例对象上面引用使用store配置项了。

import Vue from "vue"
import App from "./App.vue"
import vueResource from 'vue-resource'

//引入store
// import store from './store/index.js'
// 对于index.js,可以忽略的!因为vue会默认找index开头的。
import store from './store'
Vue.config.productionTip = false;


const vm = new Vue({
	el:'#app',
	render:h=>h(App),
	// store:store,同样对象的简写形式。
	store,
})

//打印查看。
console.log(vm)

store配置项就会多下面的一些内容:
在这里插入图片描述

2.3 Vue的注意事项


注意事项:

  • 因为vue加载一个js文件,会先将所有import导入的文件加载完成,再去加载其他的信息。跟顺序没有关系。
    在这里插入图片描述

因为上图这种问题,Vuex插件在use使用前,会报如下错误:

  • 因为,Vue.use(vuex)使用插件js命令必须在new Vuex.Store({…})的使用对象的前面才可以。不然会报下图错误!
    在这里插入图片描述

针对上面的错误解决办法就是将Vue.use()放到我们导入的文件,让他们的js代码执行顺序进行调整!!

2.4 Vuex的使用大体流程


Count.vue文件:

<template>
	<div>
		<!-- 
			在模板中,我们不用使用this , 调用的$store就是this当前组件对象默认。
				自然我们就能从state对象中拿到sum值。
		-->
		<h1>当前求和为:{{$store.state.sum}}</h1>
		<select v-model="n">
			<option :value="1">1</option>
			<option :value="2">2</option>
			<option :value="3">3</option>
		</select>
		<button @click="increment">+</button>
	</div>
</template>

<script>
	export default{
		name:'Count',
		data(){
			return{
				n:1,//用户选择的数字
			}
		},
		methods:{
			increment(){
				this.$store.dispatch('jia',this.n)
			}
		},
	}
</script>

<style scoped>
	button{
		margin-left: 5px;
	}
</style>

src/store/index.js文件:

// 该文件用于创建Vuex中最为核心的store

//引入Vue,使用插件
import Vue from 'vue'
//引入Vuex
import Vuex from 'vuex'

//引入Vuex的插件
//解决before的问题错误。
Vue.use(Vuex)

// 准备actions 用于响应组件中的动作
const actions  = {
	
	/*
		对应的设置jia函数。
			再次提醒这里的jia(){}是简写形式。本质就是jia:function(){}。
		
		这里的两个参数context,value分别是:
			context:一个携带部分功能的store(官方规定参数名是context上下文,实际上无所谓)。
			value:发送过来的值。
	*/
	jia(context,value){
		console.log("actions中的jia被调用了")
		
		// console.log(context)
		// console.log(value)
		
		//将数据发送给mutations
		context.commit('JIA',value)
	}
}

// 准备mutations 用于操作数据(state状态)
const mutations = {
	/*
		同样对应actions的commit。
			也携带了两个参数state和value:
				state:就是Vuex中的state对象,
				value:就是传过来的值。
		在mutations中,对state对象进行操作。	
	*/
	JIA(state,value){
		console.log("mutations中的JIA被调用了")
		
		// console.log(state)
		// console.log(value)
		
		//对state进行操作。
		state.sum += value
	}
}

// 准备state 用于存储数据
const state = {
	sum:0//当前和
}

//创建store
const store = new Vuex.Store({
	// actions:actions,
	// mutations:mutations,
	// state:state,
	//简写为一下形式:
	actions,
	mutations,
	state,
})

//对于当前文件我们要让外部文件使用,就必须要暴露相关信息。
//暴露store
export default store
//这样外部import导入的使用拿到的就是store这个对象

这样完成了对Vuex中state对象的sum的读写操作,流程也就是这样!

需要注意的是,对于数据或者一些业务逻辑,必须要添加到actions中,不能写到mutations中!!

  • 一定分号层次,actions就是负责处理数据业务逻辑的。
  • mutations就是负责修改state的数据的。

3. Vuex实现 求和案例


Count.vue组件:

<template>
	<div>
		<!-- 
			在模板中,我们不用使用this , 调用的$store就是this当前组件对象默认。
				自然我们就能从state对象中拿到sum值。
		-->
		<h1>当前求和为:{{$store.state.sum}}</h1>
		<select v-model="n">
			<option :value="1">1</option>
			<option :value="2">2</option>
			<option :value="3">3</option>
		</select>
		<button @click="increment">+</button>
		<button @click="decrement">-</button>
		<button @click="incrementOdd">当前求和为奇数在加</button>
		<button @click="incrementWait">等一等在加</button>
	</div>
</template>

<script>
	export default{
		name:'Count',
		data(){
			return{
				n:1,//用户选择的数字
			}
		},
		methods:{
			increment(){
				//对于没有业务逻辑的就不需要走actions了,我们直接commit就可以了。
				this.$store.commit('JIA',this.n)
			},
			decrement(){
				this.$store.commit('JIAN',this.n)
			},
			incrementOdd(){
				this.$store.dispatch('jiaOdd',this.n)
			},
			incrementWait(){
				this.$store.dispatch('jiaWait',this.n)
			},
		},
	}
</script>

<style scoped>
	button{
		margin-left: 5px;
	}
</style>

src/store/index.js文件:

// 该文件用于创建Vuex中最为核心的store

//引入Vue,使用插件
import Vue from 'vue'
//引入Vuex
import Vuex from 'vuex'

//引入Vuex的插件
//解决before的问题错误。
Vue.use(Vuex)

// 准备actions 用于响应组件中的动作
const actions  = {
	
	/*
		对应的设置jia函数。
			再次提醒这里的jia(){}是简写形式。本质就是jia:function(){}。
		
		这里的两个参数context,value分别是:
			context:一个携带部分功能的store(官方规定参数名是context上下文,实际上无所谓)。
			value:发送过来的值。
	*/
	jiaOdd(context,value){
		console.log("actions中的jiaOdd被调用了")
		if(context.state.sum % 2){
			context.commit('JIAODD',value)
		}
	},
	jiaWait(context,value){
		console.log("actions中的jiaWait被调用了")
		setTimeout(()=>{
			context.commit('JIANWAIT',value)
		},500)
	}
}

// 准备mutations 用于操作数据(state状态)
const mutations = {
	/*
		同样对应actions的commit。
			也携带了两个参数state和value:
				state:就是Vuex中的state对象,
				value:就是传过来的值。
		在mutations中,对state对象进行操作。	
	*/
	JIA(state,value){
		console.log("mutations中的JIA被调用了")
		
		// console.log(state)
		// console.log(value)
		
		//对state进行操作。
		state.sum += value
	},
	
	JIAN(state,value){
		console.log("mutations中的JIAN被调用了")
		state.sum -= value
	},
	JIAODD(state,value){
		console.log("mutations中的JIAODD被调用了")
		state.sum += value
	},
	JIANWAIT(state,value){
		console.log("mutations中的JIANWAIT被调用了")
		state.sum += value
	}
}

// 准备state 用于存储数据
const state = {
	sum:0//当前和
}

//创建store
const store = new Vuex.Store({
	// actions:actions,
	// mutations:mutations,
	// state:state,
	//简写为一下形式:
	actions,
	mutations,
	state,
})

//对于当前文件我们要让外部文件使用,就必须要暴露相关信息。
//暴露store
export default store
//这样外部import导入的使用拿到的就是store这个对象

在这里插入图片描述

4. Vuex的开发者工具


Vue和Vuex都是由vue团队打造出来的。

这个团队设计Vue的开发者工具中,也包含了Vuex的开发者工具。

在这里插入图片描述
在这里插入图片描述


图下,也符合了为什么官方认定的参数叫做context上下文的意思了。
在这里插入图片描述

5. Vuex中的 getters配置项

5.1 getters介绍和使用


getters的作用:当state中的数据需要经过加工后再使用时,可以使用getters加工。

src/store/index.js文件:

import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)

const actions  = {
	//加法不需要经过逻辑运算获取啥的。
}

const mutations = {
	JIA(state,value){
		console.log("mutations中的JIA被调用了")
		state.sum += value
	}
}

const state = {
	sum:0//当前和
}

//准备getters,用于将state中的数据进行加工
const getters = {
	bigSum(state){
		return state.sum*10
	}
}

const store = new Vuex.Store({
	actions,
	mutations,
	state,
	//不要忘记在store中配置
	getters
})

export default store

Count.vue文件:

<template>
	<div>
		<h1>当前求和为:{{$store.state.sum}}</h1>
		<h3>当前求和放大10倍后:{{$store.getters.bigSum}}</h3>
		<select v-model="n">
			<option :value="1">1</option>
			<option :value="2">2</option>
			<option :value="3">3</option>
		</select>
		<button @click="increment">+</button>
	</div>
</template>

<script>
	export default{
		name:'Count',
		data(){
			return{
				n:1,//用户选择的数字
			}
		},
		methods:{
			increment(){
				this.$store.commit('JIA',this.n)
			},
		},
		mounted(){
			console.log(this.$store)
		}
	}
</script>

<style scoped>
	button{
		margin-left: 5px;
	}
</style>

在这里插入图片描述

5.2 总结


在这里插入图片描述

6. Vuex中的 四个map方法

6.1 一些注意事项


键值对的一些注意事项:

mounted(){
/*
	注意事项:
		对象中键值对,key键的本身就是字符串,
		就像下面的sum原型就是'sum',只不过精简了。
		但是value值,必须指定好!没有精简!!
		
	mapState只能操作state中的数据。像上面的bigSum是getters中的内容。
*/
const x = mapState({
	he:'sum',
	xuexiao:'school',
	xueke:'subject'
})
console.log(x)
}

es6语法: …的作用。
在这里插入图片描述

6.2 Vuex中的 mapState


mapState就是映射状态,意思就是帮忙生成操作state的代码。一般应用到计算属性中。

效果就像下面的计算属性注释中的内容一样:

<template>
	<div>
		<h1>当前求和为:{{he}}</h1>
		<h3>当前求和放大10倍后:{{bigSum}}</h3>
		<h3>我在{{xuexiao}} ,学习{{xueke}}</h3>
		<select v-model="n">
			<option :value="1">1</option>
			<option :value="2">2</option>
			<option :value="3">3</option>
		</select>
		<button @click="increment">+</button>
		<button @click="decrement">-</button>
		<button @click="incrementOdd">当前求和为奇数在加</button>
		<button @click="incrementWait">等一等在加</button>
	</div>
</template>

<script>
	import {mapState} from 'vuex'
	export default{
		name:'Count',
		data(){
			return{
				n:1,//用户选择的数字
			}
		},
		computed:{
			/*
				靠自己写的计算属性
				he(){
					return this.$store.state.sum
				},
				xuexiao(){
					return this.$store.state.school
				},
				xueke(){
					return this.$store.state.subject
				},
			*/
		   
			//靠mapState生成的类似上面计算属性的效果:
			//es6语法 ...相当于合并了mapState
			//
			...mapState({
				he:'sum',
				xuexiao:'school',
				xueke:'subject'
			}),
			
			bigSum(){
				return this.$store.getters.bigSum
			},
		},
		methods:{
			increment(){
				this.$store.commit('JIA',this.n)
			},
			decrement(){
				this.$store.commit('JIAN',this.n)
			},
			incrementOdd(){
				this.$store.dispatch('jiaOdd',this.n)
			},
			incrementWait(){
				this.$store.dispatch('jiaWait',this.n)
			},
		},
		mounted(){
		}
	}
</script>

<style scoped>
	button{
		margin-left: 5px;
	}
</style>

在这里插入图片描述


mapState有两种写法一种是对象写法,一种是数组写法:

  • mapState对象写法:
//贴合上面内容,这里的键就是函数中的键,值就是this.$store.state.value的value值。
mapState({
	he:'sum',
	xuexiao:'school',
	xueke:'subject'
})
  • mapState数组写法:
computed:{
	/*
		靠自己写的计算属性:
		当键名是sum , state对应的属性也是sum就可以用数组形式来描述。
		sum(){
			return this.$store.state.sum
		},
		school(){
			return this.$store.state.school
		},
		subject(){
			return this.$store.state.subject
		},
	*/
   
	//如何修改的内容像上面的sum,school等都一样!!
	//就可以用数组形式来写!
	...mapState(['sum','school','subject']),
	
	bigSum(){
		return this.$store.getters.bigSum
	},
},

6.2 Vuex中的 mapgetters


和mapState一样,mapState对应的是$store中的state状态;而mapGetters是对应的是$store的getters配置项中的内容。

// bigSum(){
// 	return this.$store.getters.bigSum
// },

// ...mapGetters(bigSum:'bigSum'), //对象写法
...mapGetters(['bigSum']) //数组写法

将mapState和mapGetters整合一起,就发现代码精简了不少。mapState和mapGetters就是用来精简代码的。

<template>
	<div>
		<h1>当前求和为:{{sum}}</h1>
		<h3>当前求和放大10倍后:{{bigSum}}</h3>
		<h3>我在{{school}} ,学习{{subject}}</h3>
		<select v-model="n">
			<option :value="1">1</option>
			<option :value="2">2</option>
			<option :value="3">3</option>
		</select>
		<button @click="increment">+</button>
		<button @click="decrement">-</button>
		<button @click="incrementOdd">当前求和为奇数在加</button>
		<button @click="incrementWait">等一等在加</button>
	</div>
</template>

<script>
	import {mapState,mapGetters} from 'vuex'
	export default{
		name:'Count',
		data(){
			return{
				n:1,//用户选择的数字
			}
		},
		computed:{
			...mapState(['sum','school','subject']),
			...mapGetters(['bigSum']) //数组写法
		},
		methods:{
			increment(){
				this.$store.commit('JIA',this.n)
			},
			decrement(){
				this.$store.commit('JIAN',this.n)
			},
			incrementOdd(){
				this.$store.dispatch('jiaOdd',this.n)
			},
			incrementWait(){
				this.$store.dispatch('jiaWait',this.n)
			},
		},
		mounted(){
		}
	}
</script>

<style scoped>
	button{
		margin-left: 5px;
	}
</style>

6.3 MapActions 和 MapMutations


MapMutations,MapActions与上面两个Map方法操作一样的,作用也都一样,就是为了帮助我们生成函数,简化代码,简化操作。


MapMutations是生成对应的方法,方法中会调用commit方法,跳过actions直接联系mutations对象。

  • MapMutations的对象写法:
methods:{
/* 
	//注意event事件对象!!!,需要我们在前面传递参数!!!
	//如果不传递参数那么默认value值就是event对象了。
	increment(value){
		this.$store.commit('JIA',value)
	},
	decrement(value){
		this.$store.commit('JIAN',value)
	},
*/
//代码效果如上面代码,注意value不是我们的this.n了,而是一个事件!
...mapMutations({increment:'JIA',decrement:'JIAN'}),

},
  • MapMutation的数组写法:
/* 
	JIA(value){
		this.$store.commit('JIA',value)
	},
	JIAN(value){
		this.$store.commit('JIAN',value)
	},
*/
//mapMutations数组写法,一样数组写法就是要求二者相同!
...mapMutations(['JIA','JIAN'])

mapActions是生成对应的方法,方法中会调用dispatch方法,去联系actions对象。

  • mapActions的对象写法:
methods:{
	/*
		incrementOdd(){
			this.$store.dispatch('jiaOdd',this.n)
		},
		
		incrementWait(){
			this.$store.dispatch('jiaWait',this.n)
		},
	*/
	//对象形式写法
	...mapActions({incrementOdd:'jiaOdd',incrementWait:'jiaWait'})
}
  • mapActions的数组写法:
methods:{
	/*
		jiaOdd(){
			this.$store.dispatch('jiaOdd',this.n)
		},
		
		jiaWait(){
			this.$store.dispatch('jiaWait',this.n)
		},
	*/
	//数组形式写法
	...mapActions(['jiaOdd','jiaWait'])
	
},

所有代码效果:

<template>
	<div>
		<h1>当前求和为:{{sum}}</h1>
		<h3>当前求和放大10倍后:{{bigSum}}</h3>
		<h3>我在{{school}} ,学习{{subject}}</h3>
		<select v-model="n">
			<option :value="1">1</option>
			<option :value="2">2</option>
			<option :value="3">3</option>
		</select>
		<button @click="JIA(n)">+</button>
		<button @click="JIAN(n)">-</button>
		<button @click="jiaOdd(n)">当前求和为奇数在加</button>
		<button @click="jiaWait(n)">等一等在加</button>
	</div>
</template>

<script>
	import {mapState,mapGetters,mapMutations,mapActions} from 'vuex'
	export default{
		name:'Count',
		data(){
			return{
				n:1,//用户选择的数字
			}
		},
		computed:{
			...mapState(['sum','school','subject']),
			...mapGetters(['bigSum']) //数组写法
		},
		methods:{
			...mapMutations(['JIA','JIAN']),
			...mapActions(['jiaOdd','jiaWait'])
			
		},
		mounted(){
		}
	}
</script>

<style scoped>
	button{
		margin-left: 5px;
	}
</style>

6.4 总结


四个map的作用就是为了简化代码,操作方法。让vue给我生成函数代码。

请添加图片描述

7. Vuex的模块化(namespaced)

7.1 Vuex的模块化


在这里插入图片描述

我们将不同的信息按照对象的形式,给他们分离出来,实现一个中模块化的效果。

src/store/index.js文件:

import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)

//我们将不同相关的配置分别封装台不同的对象参数中。

//求和相关的配置
const conuntOptions = {
	actions:{
		jiaOdd(context,value){
			console.log("actions中的jiaOdd被调用了")
			if(context.state.sum % 2){
				context.commit('JIAODD',value)
			}
		},
		jiaWait(context,value){
			console.log("actions中的jiaWait被调用了")
			setTimeout(()=>{
				context.commit('JIANWAIT',value)
			},500)
		}
	},
	mutations:{
		JIA(state,value){
			console.log("mutations中的JIA被调用了")
			state.sum += value
		},
		JIAN(state,value){
			console.log("mutations中的JIAN被调用了")
			state.sum -= value
		},
		JIAODD(state,value){
			console.log("mutations中的JIAODD被调用了")
			state.sum += value
		},
		JIANWAIT(state,value){
			console.log("mutations中的JIANWAIT被调用了")
			state.sum += value
		},
	},
	state:{
		sum:0,//当前和
		school:'清华大学',
		subject:'java高级程序员',
	},
	getters:{
		bigSum(state){
			return state.sum*10
		}
	}
}

//人员管理相关的配置
const personOptions = {
	actions:{},
	mutations:{
		ADD_PERSON(state,value){
			console.log("mutations中的ADD_PERSON被调用了")
			state.personList.unshift(value);
		}
	},
	state:{
		personList:[
			{id:'001',name:'张三'}
		]
	},
	gettes:{}
}


//使用modules这种模块化的效果实现起来更加方便
export default new Vuex.Store({
	modules:{
		countAbout:conuntOptions,
		personAbout:personOptions
	}
})

Count.vue文件:

<template>
	<div>
		<h1>当前求和为:{{countAbout.sum}}</h1>
		<h3>我在{{countAbout.school}} ,学习{{countAbout.subject}}</h3>
		<h3 style="color: red;">Person组件的总人数是{{personAbout.personList.length}}</h3>
		<select v-model="n">
			<option :value="1">1</option>
			<option :value="2">2</option>
			<option :value="3">3</option>
		</select>
		<button @click="JIA(n)">+</button>
		<button @click="JIAN(n)">-</button>
		<button @click="jiaOdd(n)">当前求和为奇数在加</button>
		<button @click="jiaWait(n)">等一等在加</button>
	</div>
</template>

<script>
	import {mapState,mapGetters,mapMutations,mapActions} from 'vuex'
	export default{
		name:'Count',
		data(){
			return{
				n:1,//用户选择的数字
			}
		},
		computed:{
			//这样我们直接通过countAbout和personAbout拿到数据。
			...mapState(['countAbout','personAbout']),
			...mapGetters(['bigSum']) //数组写法
		},
		methods:{
			...mapMutations(['JIA','JIAN']),
			...mapActions(['jiaOdd','jiaWait'])
		},
	}
</script>

<style scoped>
	button{
		margin-left: 5px;
	}
</style>

在这里插入图片描述

7.2 针对map方法的 namespaced配置


当我们使用了模块化的使用,必须要给每一个模块对象配置namespaced设置为true,开启命名空间。

这样我们的map方法的第一个参数就可以指定哪一个模块下的state,mutations,actions,getters的情况。就更加的进一步简化代码了。

在这里插入图片描述

src/store/index.js文件:

import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)

//我们将不同相关的配置分别封装台不同的对象参数中。

//求和相关的配置
const conuntOptions = {
	//namespaced的默认值是false。true就是开启命名空间。
	//一旦开始了命名空间,map方法就可以使用...mapState('countAbout',['sum','school','subject'])这样的形式来识别。
	namespaced:true,
	actions:{
		jiaOdd(context,value){
			console.log("actions中的jiaOdd被调用了")
			if(context.state.sum % 2){
				context.commit('JIAODD',value)
			}
		},
		jiaWait(context,value){
			console.log("actions中的jiaWait被调用了")
			setTimeout(()=>{
				context.commit('JIANWAIT',value)
			},500)
		}
	},
	mutations:{
		JIA(state,value){
			console.log("mutations中的JIA被调用了")
			state.sum += value
		},
		JIAN(state,value){
			console.log("mutations中的JIAN被调用了")
			state.sum -= value
		},
		JIAODD(state,value){
			console.log("mutations中的JIAODD被调用了")
			state.sum += value
		},
		JIANWAIT(state,value){
			console.log("mutations中的JIANWAIT被调用了")
			state.sum += value
		},
	},
	state:{
		sum:0,//当前和
		school:'清华大学',
		subject:'java高级程序员',
	},
	getters:{
		bigSum(state){
			return state.sum*10
		}
	}
}

//人员管理相关的配置
const personOptions = {
	namespaced:true,
	actions:{},
	mutations:{
		ADD_PERSON(state,value){
			console.log("mutations中的ADD_PERSON被调用了")
			state.personList.unshift(value);
		}
	},
	state:{
		personList:[
			{id:'001',name:'张三'}
		]
	},
	gettes:{}
}


//使用modules这种模块化的效果实现起来更加方便
export default new Vuex.Store({
	modules:{
		countAbout:conuntOptions,
		personAbout:personOptions
	}
})

Count.vue文件:

<template>
	<div>
		<h1>当前求和为:{{sum}}</h1>
		<h3>当前求和放大10倍后:{{bigSum}}</h3>
		<h3>我在{{school}} ,学习{{subject}}</h3>
		<h3 style="color: red;">Person组件的总人数是{{personList.length}}</h3>
		<select v-model="n">
			<option :value="1">1</option>
			<option :value="2">2</option>
			<option :value="3">3</option>
		</select>
		<button @click="increment(n)">+</button>
		<button @click="decrement(n)">-</button>
		<button @click="jiaOdd(n)">当前求和为奇数在加</button>
		<button @click="jiaWait(n)">等一等在加</button>
	</div>
</template>

<script>
	import {mapState,mapGetters,mapMutations,mapActions} from 'vuex'
	export default{
		name:'Count',
		data(){
			return{
				n:1,//用户选择的数字
			}
		},
		computed:{
			/*
				这种写法,可以简化,让我们直接使用sum,school调用了!
					总结起来就是两种写法:
						'modules中的key值对象名' , ['map的数组形式的写法'] ;
						'modules中的key值对象名' , {方法名:'map的对象形式写法'}
				
				总结起来就是当我们使用了模块化的使用,必须要用namespaced设置为true,开启命名空间。
				这样我们的map方法的第一个参数就可以指定哪一个模块下的state,mutations,actions,getters的情况。
			*/
			...mapState('countAbout',['sum','school','subject']),
			...mapState('personAbout',['personList']),
			...mapGetters('countAbout',['bigSum']) 
		},
		methods:{
			...mapMutations('countAbout',{increment:'JIA',decrement:'JIAN'}),
			...mapActions('countAbout',['jiaOdd','jiaWait'])
			
		},
	}
</script>

<style scoped>
	button{
		margin-left: 5px;
	}
</style>

7.3 对于不使用map方法 ,程序员自己commit,dispatch,如何找到对应的模块。


对于不是map方法的形式,直接commit方法或dispatch方法。

想要找到modules对应的actions或mutations就可以使用" / "来划分出来。

methods:{
	add(){
		//使用nanoid生成一个唯一的字符串
		const personObj = {id:nanoid(),name:this.name}
		/*
			对于不是map方法的形式,直接commit方法或dispatch方法。
			想要找到modules对应的actions或mutations就可以使用/来划分出来。
			模块键名:方法名
		*/
		this.$store.commit('personAbout/ADD_PERSON',personObj)
		this.name = ''
	}
}

对于手动写的getters操作:

firstPersonName(){
	console.log(this.$store)
	//对象直接获取因为有个/ ,我们不能直接this.$store.getters.personAbout/firstPersonName这不行!
	//但是对于对象我们可以换种形式,如下:
	return this.$store.getters['personAbout/firstPersonName']
}

在这里插入图片描述

8. vuex模板化完整版案例

8.1 案例


目录结构:
在这里插入图片描述

index.js文件:

import Vue from 'vue'
import Vuex from 'vuex'
//我们只需要引入就可以了
import personOptions from './Person.js'
import conuntOptions from './Count.js'
Vue.use(Vuex)

export default new Vuex.Store({
	modules:{
		countAbout:conuntOptions,
		personAbout:personOptions
	}
})

Count.js文件(专门处理求和的模块)

//求和相关的配置
const conuntOptions = {
	//namespaced的默认值是false。true就是开启命名空间。
	//一旦开始了命名空间,map方法就可以使用...mapState('countAbout',['sum','school','subject'])这样的形式来识别。
	namespaced:true,
	actions:{
		jiaOdd(context,value){
			console.log("actions中的jiaOdd被调用了")
			if(context.state.sum % 2){
				context.commit('JIAODD',value)
			}
		},
		jiaWait(context,value){
			console.log("actions中的jiaWait被调用了")
			setTimeout(()=>{
				context.commit('JIANWAIT',value)
			},500)
		}
	},
	mutations:{
		JIA(state,value){
			console.log("mutations中的JIA被调用了")
			state.sum += value
		},
		JIAN(state,value){
			console.log("mutations中的JIAN被调用了")
			state.sum -= value
		},
		JIAODD(state,value){
			console.log("mutations中的JIAODD被调用了")
			state.sum += value
		},
		JIANWAIT(state,value){
			console.log("mutations中的JIANWAIT被调用了")
			state.sum += value
		},
	},
	state:{
		sum:0,//当前和
		school:'清华大学',
		subject:'java高级程序员',
	},
	getters:{
		bigSum(state){
			return state.sum*10
		}
	}
}

export default conuntOptions

Person.js文件(专门处理person的模块)

import axios from "axios"
import {nanoid} from 'nanoid'
//人员管理相关的配置
const personOptions = {
	namespaced:true,
	actions:{
		//这里的context是当前模块的context
		addPersonWang(context,value){
			if(value.name.indexOf('王') === 0){
				context.commit('ADD_PERSON',value)
			}else{
				alert('只能添加姓王的姓名')
			}
		},
		addPersonServer(context){
			// https://api.uixsj.cn/hitokoto/get?type=social 返回语录接口
			axios.get('https://api.uixsj.cn/hitokoto/get?type=social').then(
				response => {
					const obj = {id:nanoid(),name:response.data}
					context.commit('ADD_PERSON',obj)
				},
				error => {
					alert(error.message)
				}
			)
		}
	},
	mutations:{
		ADD_PERSON(state,value){
			console.log("mutations中的ADD_PERSON被调用了")
			state.personList.unshift(value);
		}
	},
	state:{
		personList:[
			{id:'001',name:'张三'}
		]
	},
	getters:{
		//这里的state也是当前模块的state 
		firstPersonName(state){
			return state.personList[0].name
		}
	}
}

export default personOptions

Count.vue文件:

<template>
	<div>
		<h1>当前求和为:{{sum}}</h1>
		<h3>当前求和放大10倍后:{{bigSum}}</h3>
		<h3>我在{{school}} ,学习{{subject}}</h3>
		<h3 style="color: red;">Person组件的总人数是{{personList.length}}</h3>
		<select v-model="n">
			<option :value="1">1</option>
			<option :value="2">2</option>
			<option :value="3">3</option>
		</select>
		<button @click="increment(n)">+</button>
		<button @click="decrement(n)">-</button>
		<button @click="jiaOdd(n)">当前求和为奇数在加</button>
		<button @click="jiaWait(n)">等一等在加</button>
	</div>
</template>

<script>
	import {mapState,mapGetters,mapMutations,mapActions} from 'vuex'
	export default{
		name:'Count',
		data(){
			return{
				n:1,//用户选择的数字
			}
		},
		computed:{
			/*
				这种写法,可以简化,让我们直接使用sum,school调用了!
					总结起来就是两种写法:
						'modules中的key值对象名' , ['map的数组形式的写法'] ;
						'modules中的key值对象名' , {方法名:'map的对象形式写法'}
				
				总结起来就是当我们使用了模块化的使用,必须要用namespaced设置为true,开启命名空间。
				这样我们的map方法的第一个参数就可以指定哪一个模块下的state,mutations,actions,getters的情况。
			*/
			...mapState('countAbout',['sum','school','subject']),
			...mapState('personAbout',['personList']),
			...mapGetters('countAbout',['bigSum']) 
		},
		methods:{
			...mapMutations('countAbout',{increment:'JIA',decrement:'JIAN'}),
			...mapActions('countAbout',['jiaOdd','jiaWait'])
		},
	}
</script>

<style scoped>
	button{
		margin-left: 5px;
	}
</style>

Person.vue文件:

<template>
	<div>
		<h1>人员列表</h1>
		<h3 style="color: red;">上方组件的求和为:{{sum}}</h3>
		<h3>列表中第一个人的名字是:{{firstPersonName}}</h3>
		<input type="text" placeholder="请输入名字" v-model="name">
		<button @click="add">添加</button>
		<button @click="addWang">添加一个姓王的人</button>
		<button @click="addPersonServer">添加一个人,名字是一个语录</button>
		<ul>
			<li v-for="p in personList" :key="p.id">{{p.name}}</li>
		</ul>
	</div>
</template>

<script>
	import {nanoid} from 'nanoid'
	import {mapState} from 'vuex'
	export default {
		name:'Person',
		data(){
			return {
				name:''
			}
		},
		computed:{
			personList(){
				return this.$store.state.personAbout.personList
			},
			sum(){
				return this.$store.state.countAbout.sum
			},
			firstPersonName(){
				console.log(this.$store)
				return this.$store.getters['personAbout/firstPersonName']
			}
		},
		methods:{
			add(){
				const personObj = {id:nanoid(),name:this.name}
				/*
					对于不是map方法的形式,直接commit方法或dispatch方法。
					想要找到modules对应的actions或mutations就可以使用/来划分出来。
				*/
				this.$store.commit('personAbout/ADD_PERSON',personObj)
				this.name = ''
			},
			addWang(){
				const personObj = {id:nanoid(),name:this.name}
				this.$store.dispatch('personAbout/addPersonWang',personObj)
				this.name = ''
			},
			addPersonServer(){
				this.$store.dispatch('personAbout/addPersonServer')
			}
		}
	}
</script>

<style>
</style>

8.2 总结


请添加图片描述

Logo

前往低代码交流专区

更多推荐