Vuex详解-使用教程

本文对 Vuex 整个创建即使用,都有详细的步骤介绍,如果你是 Vuex 的初学者或者遗忘当做资料回顾,相信都能对你起到一定的作用

Vuex 简介与执行流程概述

  1. Vuex:是在 Vue 中实现集中式状态(数据)管理的一个 Vue 插件,对 Vue 应用中多个组件的共享状态及逆行集中式的管理(读/写),也是一种组件间通信的方法,且适用于任意组件间通信

  2. Vuex中共有五个状态 State Getter Mutation Action Module ,下面来简单介绍一下它们

    1. State:提供唯一的公共数据源,所有共享的数据统一放到 store 下的 state 存储

    2. Mutation:用于更改 state 中存储的数据

    3. Action:用来处理一些异步操作,或者处理当前方法需要进行一些复杂的业务

    4. Getter:对 state 中的数据进行加工

    5. Module:将 store 进行模块化处理

  3. 图解:

    在这里插入图片描述

  4. 执行流程如下:

在这里插入图片描述

  1. 那看了上述的图解又为什么需要 Actions 这个转交呢?假设我们现在在进行 后端API 的接口请求,我们并不知道需要传递什么值,只是发送了一个方法,dispatch('getInfo'),此时 Actions 中就会触发同名方法 getInfo,在 Actions 中我们就可以进行 API 的请求,并将获取的数据通过 commit 方法,发送给 mutations 中,让其去更新 state 中的值

    在这里插入图片描述

  2. 当然如果你更改的值是确定的,也可以直接在组件中使用 commit 去让 mutations 更新 state 中的数据

Vuex 的环境搭建

如果采用脚手架方式进行创建时勾选了Vuex,可以忽略此步骤

  1. 引入 Vuex:Vue2 安装 3 版本,Vue3 安装 4 版本

    npm install vuex@3

  2. 在 src 目录下创建 store 文件夹

  3. 在 store 文件下创建 index.js 文件

  4. 在 index.js 文件下进行如下配置:

    // 引入 Vue
    import Vue from 'vue'
    // 引入Vuex
    import Vuex from 'vuex'
    // 使用Vuex插件
    Vue.use(Vuex)
    
    // actions——用于响应组件中的传递的方法
    const actions = {}
    
    // mutations——用于操作数据 state 中的数据
    const mutations = {}
    
    // state——用于存储数据
    const state = {}
    
    // 通过 Vuex 中的 Store 方法创建并暴露store
    // 同时传入配置项
    export default new Vuex.Store({
    	actions,
    	mutations,
    	state
    })
    
  5. Tips:这里我们先配置 actions mutations state,后续的 getter 与 module 在后续会进行讲解

  6. 将配置好的 Vuex 在 main.js 文件下引入

    //引入Vue
    import Vue from 'vue'
    //引入App
    import App from './App.vue'
    //引入store
    import store from './store'
    
    //关闭Vue的生产提示
    Vue.config.productionTip = false
    
    //创建vm
    new Vue({
    	el: '#app',
    	render: h => h(App),
        // kv 一致省略 v
    	store
    })
    

Vuex 的基本使用

  1. 首先我们创建一个组件,本示例组件名为 Teacher,先搭建一下Teacher组件的基本结构,Teacher组件内容如下:

    <template>
    	<div>
    		<h1>Vuex的基本使用--Teacher</h1>
    		<input
    			type="text"
    			placeholder="输入添加老师的名称"
    			v-model="teacher.name" />
    		<br />
    		<input
    			type="text"
    			placeholder="输入添加老师的年龄"
    			v-model="teacher.age" />
    		<br />
    		<button @click="addTeacher">添加老师</button>
    		<button @click="removeTeacher">删除年龄年龄大于50的教师</button>
    		<h3>教师列表</h3>
    		<ul>
    			<li>姓名:xxx,年龄:???</li>
    		</ul>
    	</div>
    </template>
    
    <script>
    // 引入生成唯一id插件
    import { nanoid } from 'nanoid'
    
    export default {
    	name: 'Teacher',
    	data() {
    		return {
    			teacher: {
    				name: '',
    				age: null
    			}
    		}
    	},
    	methods: {
    		// 添加
    		addTeacher() {},
    
    		// 删除
    		removeTeacher() {}
    	}
    }
    </script>
    
    <style scoped>
    button {
    	margin: 10px;
    }
    </style>
    
    
  2. 然后将 Teacher 组件在 App 组件中使用,这步比较简单,就不在进行赘述了

  3. 我们先看一下添加方法按照完整的流程实现步骤:

    1. Teacher 组件中 addTeacher 方法如下:

      addTeacher() {
      	// 获取需要添加教师的姓名和年龄
      	// 利用 nanoid 生成唯一 id
      	const teacherObj = {
      		id: nanoid(),
      		name: this.teacher.name,
      		age: this.teacher.age
      	}
      	// 将获取的教室信息通过 dispatch 方法提交给 store 中的 actions 进行处理
      	// dispatch() 方法
      	// 参数一:方法名,自己随意配置,符合规范即可
      	// 参数二:传递值
      	this.$store.dispatch('addTeacher', teacherObj)
      },
      
    2. 在 store 的 index.js 文件下的 actions 下定义方法:

      const actions = {
          // 添加教师
      	// 这里的定义的方法接收两个参数
      	// 参数一:context 上下文
      	// 参数二:接收组件中使用 dispatch 传递的值
      	addTeacher: function (context, value) {
      		// 这里我们需要利用上下文中的 commit 提交到 mutations 中
      		// 我们一般约定:commit 的方法名为大写
      		// commit 方法:
      		// 参数一:方法名
      		// 参数二:传递值
      		context.commit('ADD_TEACHER', value)
      	},
      }
      
    3. 上述的 addTeacher 可能看起来有一些繁杂,我们可以简写一下,两种写法都可以,按照个人习惯即可

      // 同样我们可以将 addTeacher 方法进行简写一些
      // 我们这里只需要使用 context 的 commit 方法,可以使用解构单独提取
      addTeacher({commit}, value){
      	commit('ADD_TEACHER', value)
      },
      
    4. 在 mutations 定义方法:

      const mutations = {
          // 通过 commit 提交会自动触发 mutatios 中同名的方法
      	// mutatios 中的方法接收两个参数
      	// 参数一:当前实例的 state
      	// 参数二:commit 方法传递的值
      	ADD_TEACHER(state, value) {
      		// 将新教师的信息更新到 state 仓库中
      		state.teacherList.unshift(value)
      	},
      }
      
    5. state 中内容如下:state 中的数据会直接解析并引用到相关的组件中

      const state = {
      	// 教师列表
      	teacherList: []
      }
      
    6. 因为开始渲染,我们需要将原来 Teacher 组件中的 ul列表 的固定模板改为 循环渲染

      <ul>
      	<!-- 模板中使用可以省略 this -->
      	<li
      		v-for="t in $store.state.teacherList"
      		:key="t.id">
      		姓名:{{ t.name }},年龄:{{ t.age }}
      	</li>
      </ul>
      
    7. 实际的运行效果大家可以可以按照步骤放入 vue 项目中运行一下

  4. 看了上述的添加方法实现,大家可能会疑惑了,为什么 mutations 中就可以完成的事情,需要经过 actions 这一步的转接呢?具体的原因我们放在后续讲解,这里可以告诉大家,如果我们需要修改的数据不需要做过多的处理,如上述示例中单纯的增删改查,且增删改查的值我们本身就拥有们就可以直接在 组件中通过 commit 方法和 mutations 对话,去更新 state 中的值,如下:

    addTeacher() {
        const teacherObj = {
    		id: nanoid(),
    		name: this.teacher.name,
    		age: this.teacher.age
    	}
        // 注意这里的方法名需要修改为 mutations 中的方法名
    	this.$store.commit('ADD_TEACHER', teacherObj)
    }
    
  5. 那通过删除年龄大于50岁这个方法来给大家演示一下 actions 的作用,上述重复过如 dispatch 和 commit 等方法的说明后续就不再进行注解了,下面来看一下具体的实现步骤:

    1. 在本次方法的演示中我已经提前通过 addTeacher 添加方法添加了一些教师数据,如图:

      在这里插入图片描述

    2. Teacher 组件中 removeTeacher方法如下:

      // 删除
      removeTeacher() {
          // 通过 this.$store.state.teacherList 就可以获取 state 中的 teacherList
      	const teacherList = this.$store.state.teacherList
      	// 发送删除方法
      	this.$store.dispatch('removeTeacher', teacherList)
      }
      
    3. 在 actions 下定义方法:

      const actions = {
          removeTeacher({ commit }, value) {
      		// 筛选其中年龄大于 50 的教师
      		const result = value.filter(item => item.age < 50)
      		// 若是对 filter 方法不熟悉,大家可以自己百度在回顾一下
      		commit('REMOVE_TEACHER', result)
      	}
      }
      
    4. 在 mutations 下定义方法:

      const mutations = {
       	REMOVE_TEACHER(state, value) {
      		state.teacherList = value
      	},
      }
      
    5. 结果如图:

      在这里插入图片描述

    6. 通过删除教师这个案例,相信大家可以看出 actions 的一些作用,通过 actions 可以处理一些代码的业务逻辑,最重要的是在此处进行一些后端接口的请求,将请求的数据带给 mutations,大致方式差不多,这里就给大家写一段示例代码进行演示,如下:

      const acions = {
          // 假设当前接口获取的书籍信息
          // 因为是在 actions 中发送数据请求。就不需要携带值   
          getBookInfo({commit}){
              // 关于 axios 本示例就不进行讲解了
           	axios.get('https://xxx/v1/books').then( res =>{
                  commit('GET_BOOK_INFO', res)
              })  
          }
      }
      

context 上下文

  1. 这里我们对 actions 中的 context 进行一些详细的解析

  2. 首先我们可以先看一下 context 的打印结果

    在这里插入图片描述

  3. 通过上述打印结果我们可以看到具备不少的方法,通过这些方法可以将 context 理解为一个简化版的 store,这里我重点给大家讲解一下 commit dispatch state

  4. commit:之前的示例中也给大家说明过,可以传递两个参数

    1. 参数一:传递给 mutations 中的方法名,一般我们约定为大写,当然可以自己自定义,符合命名规范即可
    2. 参数二:需要传递的值
    3. 当 commit 执行后,mutations 中 和 commit 中 参数一 的同名方法会自动调用
  5. state:获取 state 仓库中的数据,拿到这个数据的作用我们与 dispatch 一起进行讲解

  6. dispatch:大家可能不理解为什么这里需要 dispatch,在 actions 中可能会出现一个方法中内部业务复杂,代码过多情况下,就会显得这个方法十分的臃肿,不利于维护和阅读,我们知道 dispatch 可以触发 actions ,那么我们就可以通过再次 dispatch 进行方法中业务分离,抽取一部分代码放入其他方法执行,我们来看一下示例:

    const acions = {
        // 此处的仅作用于演示,因此方法名设计的比较随意
        demo1(context){
            // 这里用一句输出代替实际执行的业务
            console.log('处理的第一部分逻辑')
            // 假设最后得到的结果使用 result 变量接收,并需要对这个结果做进一步的处理
            // 我们就可以使用 dispatch 触发另外一个方法进行处理
            context.dispatch('demo2', result)
        },
        
        demo2(context, value) {
            console.log('对数据value进行了处理')
            // 此时我们业务完成,可以进行提交
            context.commit('DEMO_2', value)
            // 如果我们还需要进一步的分离,可以再次进行 dispatch
    	}
    }
    
  7. 相信现在大家对于 context 已经了有了一些大概的了解了,下面我们在介绍一下 Getter

Getter 的使用

  1. 现在我们需要给最开始 index.js 文件在添加一项配置

    import Vue from 'vue'
    import Vuex from 'vuex'
    Vue.use(Vuex)
    
    const actions = {
    	removeTeacher({ commit }, value) {
    		const result = value.filter(item => item.age < 50)
    		commit('REMOVE_TEACHER', result)
    	},
    
    	addTeacher({ commit }, value) {
    		commit('ADD_TEACHER', value)
    	}
    }
    
    const mutations = {
    	REMOVE_TEACHER(state, value) {
    		state.teacherList = value
    	},
    	ADD_TEACHER(state, value) {
    		state.teacherList.unshift(value)
    	}
    }
    
    // 添加 getters
    // getters 的方法可以接收一个参数 state
    // 依靠返回值决定值,与计算属性类似,计算属性不了解的可以自己查阅一下资料
    const getters = {}
    
    const state = {
    	teacherList: []
    }
    
    export default new Vuex.Store({
    	actions,
    	mutations,
    	state,
    	getters
    })
    
  2. 那我们现在先来使用一下 getters ,getters 在最开始我们就提到过,主要是对 state 中的数据进行加过,示例如下:

    const getters = {
    	// 所有年龄小于50岁的教室名称后面都标记 *
    	addSing(state) {
    		const newArr = []
    		state.teacherList.forEach(item => {
    			if (item.age < 50) {
    				const obj = {
    					id: item.id,
    					name: item.name + '*',
    					age: item.age
    				}
    				newArr.push(obj)
    			} else {
    				newArr.push(item)
    			}
    		})
    		// 此处为了展示不一样的效果,选择返回一个新的数组,避免修改原数组
    		return newArr
    	}
    }
    
  3. 那如何获取 getters 中的数据呢,我们在 Teacher 组件中演示一下获取的方式

    mounted() {
    	console.log(this.$store.getters.addSing)
    },
    
  4. 如果实在模板中省略 this 即可,我们使用 getters 加工后的数据渲染展示一下,结构如下:

    <h3>教师列表--state</h3>
    <ul>
    	<li
    		v-for="t in $store.state.teacherList"
    		:key="t.id">
    		姓名:{{ t.name }},年龄:{{ t.age }}
    	</li>
    </ul>
    <h3>教师列表--getters</h3>
    <ul>
    	<li
    		v-for="a in $store.getters.addSing"
    		:key="a.id">
    		姓名:{{ a.name }},年龄:{{ a.age }}
    	</li>
    </ul>
    
  5. 渲染如图:

    在这里插入图片描述

  6. 以上就是 getter 的基本使用,大家理解为 state 的加工厂就好了

mapState 详解

  1. 我们上述的示例中已经实现了整个 Vuex 的基本使用,但是不知道大家有没有发现一段代码总是在重复,$store.state.xxx,特别是在模板中,看起来就比较臃肿,或许也可以说放进计算属性中,就可以改变模板中的代码,但是这样计算属性在获取的时候,this.$store.state.xxx 是不是也是重复了呢,这时候就是我们要说的关键所在了,mapState,它可以帮助我们省去这些重复的代码

  2. 首先我们先给教室列表一些初始数据,方便我们获取看到结果

    const state = {
    	teacherList: [
    		{ id: '001', name: '田七', age: 25 },
    		{ id: '002', name: '赵六', age: 22 },
    		{ id: '003', name: '王五', age: 56 },
    		{ id: '004', name: '李四', age: 33 },
    		{ id: '005', name: '张三', age: 60 }
    	]
    }
    
  3. 首先我们需要在 Teacher 组件中 Vuex 中引入 mapState,如果大家对于这种引入方式存在疑惑的话,可以去回顾一下模块化的知识

    // 引入 Vuex 中的 mapState
    import { mapState } from 'vuex'
    
  4. 引入之后我们先来看一下 mapState

    mounted() {
    	// mapState要求我们传入一个配置对象
    	// 配置对象中的 k 表示我们在组件中使用这个数据的变量名
    	// 配置对象中的 v 表示在 state 中查找的数据名称
    	//  - 我们知道,这个 k 值其实是一个字符串,只是平常简写了,在执行的时候还是会自动包裹一个字符串,所以 v 值不仅要使用 state 中的名称,还需要包裹一个字符串
    	//  - 如果不包裹字符串就表示当前页面的一个变量
    	const res = mapState({ tList: 'teacherList' })
    	console.log(res)
    },
    
  5. 通过上述代码可以得到如下输出,如图:

    在这里插入图片描述

  6. 最外层可以看到,是一个对象,内部是一个函数,函数名叫 tList

  7. 下面我们来使用一下 mapState,刚刚我们提到,可以使用计算属性让模板中的代码进行精简,那我们在计算属性中使用一下 mapState,示例如下:

    computed: {
        // 在这里使用 ... 是展开运算符的语法,我们刚才打印的时候可以发现是一个对象里面包裹函数
    	// 所以使用 ... 展开 mapState,如果没有理解的朋友可以记住这种写法,或者回顾一些 es6 的展开运算符
    	//  - 展开之后 tList 就是一个函数,且这个函数的返回值就是 state 中获取的值,所以无法使用 kv 一致省略 v,因为这种简写形式,后续的 v 会被当成是一个变量解析
    	...mapState({ tList: 'teacherList' })
    },
    
  8. 我们在得到这个值之后有什么作用呢?模板中我们就可以省略 $store.state.xxx,一长串的引用,直接使用 tList 替代即可,示例如下:

    <h3>教师列表--state</h3>
    <ul>
    	<li
    		v-for="t in tList"
    		:key="t.id">
    		姓名:{{ t.name }},年龄:{{ t.age }}
    	</li>
    </ul>
    
  9. 可以看到是不是精简了很多,同样在 js 中也可以直接使用 this.tList 即可获取,是不是也简洁了许多,哪还能不能在简单一些呢,答案当然可以,上述展示的只是对象写法,简写可不是 kv 一直省略 v,为什么不是可以在看看上述的注解,而是数组写法,示例如下:

    computed: {
        // 数组写法
    	// 这种写法的意思是:在计算属性中,属性名叫 teacherList,且在 state 中寻找的数据也叫 teacherList
    	...mapState(['teacherList'])
    },
    
  10. 运行结果如图:

    在这里插入图片描述

  11. 使用数组写法,模板中的 tList 名称也需要换成 teacherList,这一步就不在进行代码演示了,大家自行修改即可,经过对象写法和数组写法按照个人习惯即可,不过还是更推荐大家使用数组写法,毕竟可以从一定程度上避免重新取名的烦恼,如果对象写法取同名是不是还是数组写法更好呢

  12. 可能写到这有些小伙伴会有一些疑惑,这个可以在 methods 中使用吗,也是可以的,也是使用扩展运算符展开即可,但是这样获取的数据在模板中无法使用,所以就没有太大的必要了,还是一样给大家写一段示例,示例如下:

    methods: {
        ...mapState(['teacherList'])
    }
    

mapGetters 详解

  1. 经过 mapState 的使用之后,相信大家对于怎么使用 mapGetters 想必也不是什么难事,那我就不在进行赘述了,直接使用代码给大家演示一下

  2. 在组件中,引入 mapGetters

    import { mapState, mapGetters } from 'vuex'
    
  3. 在计算属性中使用 mapGetters

    computed: {
        // 同理,使用数组写法引入,对象写法请大家参考 mapState 的对象写法
    	...mapGetters(['addSing'])
    },
    
  4. 同步修改模板中的数据渲染

    <h3>教师列表--getters</h3>
    <ul>
    	<li
    		v-for="t in addSing"
    		:key="t.id">
    		姓名:{{ t.name }},年龄:{{ t.age }}
    	</li>
    </ul>
    
  5. 运行结果如图:

在这里插入图片描述

mapMutations 详解

  1. 既然存在 mapState 与 mapGetters,那肯定也具备 mapActions 与 mapMutations,我们先讲解 mapMutations,mapActions 后续在讲解

  2. 为了方便演示,我们重新定义一个方法,点击按钮 state 中的 num 就 + 1,在 html 结构添加一个展示框和按钮,如下:

    <h2>state的num为:xxx</h2>
    <button @click="addOne">点击num自增1</button>
    
  3. 页面样式如图:

    在这里插入图片描述

  4. 在 state 中初始化 num: 0,就不在演示了

  5. 引入 mapMutations

    import { mapState, mapGetters, mapMutations } from 'vuex'
    
  6. 因为自增 + 1的方法属于简单的自增,我们可以直接与 mutations 对话,在方法中使用 mapMutations ,示例如下:

    methods:{
        // addOne 为当前组价中触发的事件回调名称,ADD_ONE 为在 mutations 中的名称方法
    	// 同时我们发现 addOne 并没有传送自增的值过去,那应该怎么传呢,可以在定义事件的时候传递一个参数
        // 他会自动帮我们触发 commit 方法与 mutations 对话
        ...mapMutations({ addOne: 'ADD_ONE' })
    }
    
  7. 在模板中定义事件的时候传递一个参数,修改如下:

    <button @click="addOne(1)">点击num自增1</button>
    
  8. 记得在 mutations 中定义方法,ADD_ONE,示例如下:

    const mutations = {
    	// 自增 + 1
    	ADD_ONE(state, value) {
    		state.num += value
    	}
    }
    
  9. 即可实现自增 + 1的需求,那么是不是只能在定义事件的时候传递参数呢?也不尽然,还可以使用事件触发方法的写法,我们一起看一下,html 中将参数取消,修改如下:

    <button @click="addOne">点击num自增1</button>
    
  10. addOne 方法如下:

    methods:{
        // 点击触发 addOne 方法时,我们在调用一下另外的方法,并传递值
    	addOne() {
    		this.jiaOne(1)
    	}
    }
    
  11. 可能大家也猜到了,jiaOne 就是在 mapMutations 中触发的方法,修改如下:

    methods:{
        // 点击触发 addOne 方法时,我们在调用一下另外的方法,并传递值
    	addOne() {
    		this.jiaOne(1)
    	},
        ...mapMutations({ jiaOne: 'ADD_ONE' })     
    }
    
  12. 后者这种写法比较繁杂一些,具体使用那种写法,根据需求和个人习惯而定,既然存在对象写法,那一定也会有数组写法,就是名称都一致即可,示例如下:

    methods:{
        // 记得事件名也需要同步修改成 ADD_ONE,数组写法大家脑海中编写一次就可以发现,不是很好用,所以不推荐
        // 大家理解和知道即可
        ...mapMutations(['ADD_ONE'])     
    }
    

mapActions 详解

  1. mapActions 与 mapMutations 就像一对兄弟,使用的方法和 mapMutations 一样,所以我们直接进行演示

  2. 我们演示就采用开始定义的删除年龄大于 50 的方法,如果有一点遗忘的小伙伴,可自行回看一下,首先我们需要定义事件的时候传递一个参数,所以 html 结构中也需要修改一下,示例如下:

    <!-- 此处传递的参数 teacherList 来自于 mapState  -->
    <button @click="removeTeacher(teacherList)">删除年龄年龄大于50的教师</button>
    
  3. 在 methods 中使用 mapActions

    methods:{
        // 同理,会自动帮我们触发 dispatch 方法与 actions 对话
        ...mapActions({ removeTeacher: 'removeTeacher' })
    }
    
    
  4. 执行结果如图:

    在这里插入图片描述

  5. 可以看到结果运行和之前别无二致,利用两个函数调用传递参数数组写法就不在进行展示了,大家有兴趣可以自行练习一下

module 详解

  1. 经历这么久的叙述,我们终于进入到了最后一关模块化,也是至关重要的一关,项目越大越是必不可少,下面就让我们一起来使用一下

  2. 新增了 module ,那么是不是意味着配置 Vuex 的index.js 文件是不是也需要对应的变化,如下:

    import Vue from 'vue'
    import Vuex from 'vuex'
    Vue.use(Vuex)
    
    // 定义 Teacher 组件的配置
    // 将 actions mutations mutations state 放入配置项
    const teacherOptions = {
    	actions: {
    		removeTeacher({ commit }, value) {
    			const result = value.filter(item => item.age < 50)
    			commit('REMOVE_TEACHER', result)
    		},
    
    		addTeacher({ commit }, value) {
    			commit('ADD_TEACHER', value)
    		}
    	},
    	mutations: {
    		ADD_ONE(state, value) {
    			state.num += value
    		},
    
    		REMOVE_TEACHER(state, value) {
    			state.teacherList = value
    		},
    
    		ADD_TEACHER(state, value) {
    			state.teacherList.unshift(value)
    		}
    	},
    	getters: {
    		addSing(state) {
    			const newArr = []
    			state.teacherList.forEach(item => {
    				if (item.age < 50) {
    					const obj = {
    						id: item.id,
    						name: item.name + '*',
    						age: item.age
    					}
    					newArr.push(obj)
    				} else {
    					newArr.push(item)
    				}
    			})
    			return newArr
    		}
    	},
    	state: {
    		teacherList: [
    			{ id: '001', name: '田七', age: 25 },
    			{ id: '002', name: '赵六', age: 22 },
    			{ id: '003', name: '王五', age: 56 },
    			{ id: '004', name: '李四', age: 33 },
    			{ id: '005', name: '张三', age: 60 }
    		],
    		num: 0
    	}
    }
    
    export default new Vuex.Store({
    	// 使用 modules 开模块化
    	modules: {
    		// 传入配置项 teacherOptions,kv 一致省略 v
    		teacherOptions
    	}
    })
    
    
  3. 修改完成之后我们现在通过 this.$store.state来 看一下是什么,如图:

    在这里插入图片描述

  4. 是不是只有我们刚刚配置的 teacherOptions 配置对象了,那我们现在在组件中应该如何使用呢?示例如下:

    computed: {
    	// 我们通过打印 state,发现是不是只有 teacherOptions ,那么我们此处就需要修改一下引用
    	// ...mapState(['teacherList', 'num']),
    	// 直接引入配置对象 teacherOptions
    	...mapState(['teacherOptions'])
    },
    
  5. 修改了引用,那模板中引用也需要修改一下,如下:

    <h3>教师列表--state</h3>
    <ul>
    	<li
    		v-for="t in teacherOptions.teacherList"
    		:key="t.id">
    		姓名:{{ t.name }},年龄:{{ t.age }}
    	</li>
    </ul>
    
  6. 运行结果如图:

    在这里插入图片描述

  7. 那这样是不是觉得使用总需要使用 teacherOptions 作为前缀进行使用比较麻烦,有没有办法和之前一样直接使用呢,也是可以的,但是有个前提,需要开启命名空间,示例如下:

    const teacherOptions = {
        // 在配置对象的时候,开启这个命名空间
    	namespaced: true,
    	actions: {
    		removeTeacher({ commit }, value) {
    			const result = value.filter(item => item.age < 50)
    			commit('REMOVE_TEACHER', result)
    		},
    
    		addTeacher({ commit }, value) {
    			commit('ADD_TEACHER', value)
    		}
    	},
    	mutations: {
    		ADD_ONE(state, value) {
    			state.num += value
    		},
    
    		REMOVE_TEACHER(state, value) {
    			state.teacherList = value
    		},
    
    		ADD_TEACHER(state, value) {
    			state.teacherList.unshift(value)
    		}
    	},
    	getters: {
    		addSing(state) {
    			const newArr = []
    			state.teacherList.forEach(item => {
    				if (item.age < 50) {
    					const obj = {
    						id: item.id,
    						name: item.name + '*',
    						age: item.age
    					}
    					newArr.push(obj)
    				} else {
    					newArr.push(item)
    				}
    			})
    			return newArr
    		}
    	},
    	state: {
    		teacherList: [
    			{ id: '001', name: '田七', age: 25 },
    			{ id: '002', name: '赵六', age: 22 },
    			{ id: '003', name: '王五', age: 56 },
    			{ id: '004', name: '李四', age: 33 },
    			{ id: '005', name: '张三', age: 60 }
    		],
    		num: 0
    	}
    }
    
  8. 开启命名空间之后呢?我们对 mapState 进行修改,修改如下:

    computed: {
    	// ...mapState(['teacherOptions'])
    	// 我们还需要传入一个参数
    	// 参数一:配置项名称
    	// 参数二:引入配置项中的数据
    	...mapState('teacherOptions', ['teacherList'])
    },
    
  9. 在模板中使用,将引用去掉即可,如下:

    <h3>教师列表--state</h3>
    <ul>
    	<li
    		v-for="t in teacherList"
    		:key="t.id">
    		姓名:{{ t.name }},年龄:{{ t.age }}
    	</li>
    </ul>
    
  10. 运行结果大家可以自己测试一下,这里就不在进行展示了,mapGetter 的写法也是一样的,示例如下:

    computed: {
    	...mapGetters('teacherOptions', ['addSing'])
    },
    
  11. 运行结如图:

    在这里插入图片描述

  12. mapActions 写法也一样

    methods:{
        ...mapActions('teacherOptions', { removeTeacher: 'removeTeacher' }),
    }
    
  13. mapMutations 我就不在进行演示了

  14. 我们还可以在 store 文件夹新建一个 teacher.js 文件,然后引入进 index.js 文件,可以实现更好的代码分离,teacher.js 文件内容如下:

    // 默认导出
    export default {
    	namespaced: true,
    	actions: {
    		removeTeacher({ commit }, value) {
    			const result = value.filter(item => item.age < 50)
    			commit('REMOVE_TEACHER', result)
    		},
    
    		addTeacher({ commit }, value) {
    			commit('ADD_TEACHER', value)
    		}
    	},
    	mutations: {
    		ADD_ONE(state, value) {
    			state.num += value
    		},
    
    		REMOVE_TEACHER(state, value) {
    			state.teacherList = value
    		},
    
    		ADD_TEACHER(state, value) {
    			state.teacherList.unshift(value)
    		}
    	},
    	getters: {
    		addSing(state) {
    			const newArr = []
    			state.teacherList.forEach(item => {
    				if (item.age < 50) {
    					const obj = {
    						id: item.id,
    						name: item.name + '*',
    						age: item.age
    					}
    					newArr.push(obj)
    				} else {
    					newArr.push(item)
    				}
    			})
    			return newArr
    		}
    	},
    	state: {
    		teacherList: [
    			{ id: '001', name: '田七', age: 25 },
    			{ id: '002', name: '赵六', age: 22 },
    			{ id: '003', name: '王五', age: 56 },
    			{ id: '004', name: '李四', age: 33 },
    			{ id: '005', name: '张三', age: 60 }
    		],
    		num: 0
    	}
    }
    
  15. index.js 文件如下:

    import Vue from 'vue'
    import Vuex from 'vuex'
    Vue.use(Vuex)
    
    // 引入 teacher 配置项
    import teacherOptions from './teacher'
    
    export default new Vuex.Store({
    	// 使用 modules 开模块化
    	modules: {
    		// kv 一致省略 v
    		teacherOptions
    	}
    })
    
  16. 是不是看起来就更加简洁美观,且利于后续的维护呢,如果还有其他组件按照 Teacher 组件的方式在继续添加即可

多组件数据共享

  1. 新建一个组件 Student,组件需要使用 Tacher 组件的教室列表,下面我就不在分步进行演示了,直接展示 Student 组件的内容,示例如下:

    <template>
    	<div>
    		<h1>Vuex的模块化--Student</h1>
    		<h3>使用 Tacher 组件的教师列表</h3>
    		<ul>
    			<li
    				v-for="t in teacherList"
    				:key="t.id">
    				姓名:{{ t.name }},年龄:{{ t.age }}
    			</li>
    		</ul>
    	</div>
    </template>
    
    <script>
    import { mapState } from 'vuex'
    export default {
    	name: 'Student',
    	computed: {
    		...mapState('teacherOptions', ['teacherList'])
    	}
    }
    </script>
    
    <style></style>
    
    
  2. 将组件注册使用我就不在赘述了,直接大家看结果吧,如图:

    在这里插入图片描述

总结

关于 Vuex 的全部使用就已经全部介绍完毕了,最后来谈一下什么时候使用 Vuex 吧,如果你的项目并不打算开发中大型的单页面应用,那 Vuex 对你来说可能是比较繁琐的,如果你需要开发中大型项目,那么我相信 Vuex 一定是你的不二选择,感谢观看

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue.js是一个流行的JavaScript框架,它允许您构建动态Web应用程序。Vuex是一个专为Vue.js应用程序开发的状态管理模式。它允许您在应用程序中管理和维护状态,例如用户信息、购物车、主题等。Vuex将状态存储在一个集中的存储库中,称为store。Vuex的核心概念包括state、mutations、actions和getters。 - state:存储应用程序级别的状态,可以通过store.state访问。 - mutations:用于更改状态的函数,必须是同步函数。可以通过store.commit方法调用。 - actions:用于处理异步操作的函数,可以包含任意异步操作。可以通过store.dispatch方法调用。 - getters:用于从store中获取状态的函数,可以通过store.getters访问。 下面是一个简单的示例,演示如何在Vue.js应用程序中使用Vuex: 1.安装Vuex ```shell npm install vuex --save ``` 2.创建store ```javascript import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) const store = new Vuex.Store({ state: { count: 0 }, mutations: { increment (state) { state.count++ } }, actions: { incrementAsync ({ commit }) { setTimeout(() => { commit('increment') }, 1000) } }, getters: { getCount: state => { return state.count } } }) export default store ``` 3.在Vue组件中使用store ```javascript <template> <div> <p>Count: {{ count }}</p> <button @click="increment">Increment</button> <button @click="incrementAsync">Increment Async</button> </div> </template> <script> import { mapGetters, mapActions } from 'vuex' export default { computed: { ...mapGetters([ 'getCount' ]) }, methods: { ...mapActions([ 'increment', 'incrementAsync' ]) } } </script> ``` 在上面的示例中,我们创建了一个名为count的状态,并定义了一个名为increment的mutation和一个名为incrementAsync的action。我们还定义了一个名为getCount的getter,用于从store中获取count状态。在Vue组件中,我们使用mapGetters和mapActions帮助程序将getter和action映射到组件中。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值