理解vuex
vuex 是什么
- 专门在 Vue 中实现集中式状态(数据)管理的一个 Vue 插件,对 vue 应
用中多个组件的共享状态进行集中式的管理(读/写),也是一种组件间通信的方
式,且适用于任意组件间通信。 - Github 地址:https://github.com/vuejs/vuex
什么时候使用 Vuex
- 多个组件依赖于同一状态
- 来自不同组件的行为需要变更同一状态
Vuex 工作原理图
安装vuex
终端输入npm i vuex@3
注意:vuex3在vue2中使用,vuex4在vue3中使用
搭建vuex环境
-
创建文件:
src/store/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 = {} //创建并暴露store export default new Vuex.Store({ actions, mutations, state })
-
在
main.js
中创建vm时传入store
配置项...... //引入store import store from './store' ...... //创建vm new Vue({ el:'#app', render: h => h(App), store })
基本使用
-
初始化数据、配置
actions
、配置mutations
,操作文件store.js
//引入Vue核心库 import Vue from 'vue' //引入Vuex import Vuex from 'vuex' //引用Vuex Vue.use(Vuex) const actions = { //响应组件中加的动作 jia(context,value){ // console.log('actions中的jia被调用了',miniStore,value) context.commit('JIA',value) }, } const mutations = { //执行加 JIA(state,value){ // console.log('mutations中的JIA被调用了',state,value) state.sum += value } } //初始化数据 const state = { sum:0 } //创建并暴露store export default new Vuex.Store({ actions, mutations, state, })
-
组件中读取vuex中的数据:
$store.state.sum
-
组件中修改vuex中的数据:
$store.dispatch('action中的方法名',数据)
或$store.commit('mutations中的方法名',数据)
备注:若没有网络请求或其他业务逻辑,组件中也可以越过actions,即不写
dispatch
,直接编写commit
getters的使用
- 概念:当state中的数据需要经过加工后再使用时,可以使用getters加工。
- 在
store.js
中追加getters
配置...... const getters = { bigSum(state){ return state.sum * 10 } } //创建并暴露store export default new Vuex.Store({ ...... getters })
- 组件中读取数据:
$store.getters.bigSum
四个map方法的使用
首先通过import {mapState,mapGetters,mapMutations,mapActions} from 'vuex'
引入
-
mapState方法:用于帮助我们映射
state
中的数据为计算属性computed: { //借助mapState生成计算属性:sum、school、subject(对象写法) ...mapState({sum:'sum',school:'school',subject:'subject'}), //借助mapState生成计算属性:sum、school、subject(数组写法) ...mapState(['sum','school','subject']), },
-
mapGetters方法:用于帮助我们映射
getters
中的数据为计算属性computed: { //借助mapGetters生成计算属性:bigSum(对象写法) ...mapGetters({bigSum:'bigSum'}), //借助mapGetters生成计算属性:bigSum(数组写法) ...mapGetters(['bigSum']) },
-
mapActions方法:用于帮助我们生成与
actions
对话的方法,即:包含$store.dispatch(xxx)
的函数methods:{ //靠mapActions生成:incrementOdd、incrementWait(对象形式) ...mapActions({incrementOdd:'jiaOdd',incrementWait:'jiaWait'}) //靠mapActions生成:jiaOdd、jiaWait(数组形式) ...mapActions(['jiaOdd','jiaWait']) }
-
mapMutations方法:用于帮助我们生成与
mutations
对话的方法,即:包含$store.commit(xxx)
的函数methods:{ //靠mapActions生成:increment、decrement(对象形式) ...mapMutations({increment:'JIA',decrement:'JIAN'}), //靠mapMutations生成:JIA、JIAN(对象形式) ...mapMutations(['JIA','JIAN']), }
备注:mapActions与mapMutations使用时,若需要传递参数需要:在模板中绑定事件时传递好参数,否则参数是事件对象。
模块化+命名空间
-
目的:让代码更好维护,让多种数据分类更加明确。
-
修改
store.js
// 该文件用于创建Vuex中最为核心的store // 引入vuex import Vue from 'vue' // 引入Vuex import Vuex from 'vuex' // 引入求和相关的配置 import countOptions from './count' // 引入人员管理相关的配置 import personOptions from './person' import axios from 'axios' import {nanoid} from 'nanoid' // 使用Vuex插件 Vue.use(Vuex) // 求和相关的配置 const countAbout = { namespaced:true,//开启命名空间 actions:{ jiaOdd(context,value){ console.log('jiaOdd被调用了'); if(context.state.sum % 2){ context.commit('JIA',value) } }, jiaWait(context,value){ console.log('jiaWait被调用了'); setTimeout(()=>{ context.commit('JIA',value) },500) }, }, mutations:{ JIA(state,value){ state.sum += value }, JIAN(state,value){ state.sum -= value }, }, state:{ sum:0, school:'bilibili', subject:'前端', }, getters:{ bigSum(state){ return state.sum * 10; } } } // 人员管理相关的配置 export default { namespaced:true,//开启命名空间 actions:{ addPersonWang(context,value){ if(value.name.indexOf('王') === 0){ context.commit('ADD_PERSON',value) }else { alert('必须是姓王的人!') } }, addPersonServer(context){ axios.get('https://api.uixsj.cn/hitokoto/get?type=social').then( response => { context.commit('ADD_PERSON',{id:nanoid(),name:response.data}) }, error => { alert(error.message) } ) } }, mutations:{ ADD_PERSON(state,value){ state.personList.unshift(value) }, }, state:{ personList: [ {id:'1',name:'张三'} ] }, getters:{ firstPersonName(state){ return state.personList[0].name } } } // 创建并暴露store export default new Vuex.Store({ modules:{ countAbout:countOptions, personAbout:personOptions, } })
注意:每个模块都需要开启命名空间,添加namespaced:true
开启,默认为false。
-
开启命名空间后,组件中读取state数据:
//方式一:自己直接读取 this.$store.state.personAbout.list //方式二:借助mapState读取: ...mapState('countAbout',['sum','school','subject']),
-
开启命名空间后,组件中读取getters数据:
//方式一:自己直接读取 this.$store.getters['personAbout/firstPersonName'] //方式二:借助mapGetters读取: ...mapGetters('countAbout',['bigSum'])
-
开启命名空间后,组件中调用dispatch
//方式一:自己直接dispatch this.$store.dispatch('personAbout/addPersonWang',person) //方式二:借助mapActions: ...mapActions('countAbout',{incrementOdd:'jiaOdd',incrementWait:'jiaWait'})
-
开启命名空间后,组件中调用commit
//方式一:自己直接commit this.$store.commit('personAbout/ADD_PERSON',person) //方式二:借助mapMutations: ...mapMutations('countAbout',{increment:'JIA',decrement:'JIAN'}),
modules的使用(配合模块化)
- 包含多个 module
- 一个 module 是一个 store 的配置对象
- 与一个组件(包含有共享数据)对应
// 该文件用于创建Vuex中最为核心的store
// 引入vuex
import Vue from 'vue'
// 引入Vuex
import Vuex from 'vuex'
// 引入求和(countAbout)相关的配置
import countOptions from './count'
// 引入人员管理(personAbout)相关的配置
import personOptions from './person'
// 使用Vuex插件
Vue.use(Vuex)
// 创建并暴露store
export default new Vuex.Store({
modules:{
countAbout:countOptions,
personAbout:personOptions,
}
})