Vuex
概念
在Vue中实现集中式状态(数据)管理的一个Vue插件,对vue应用中多个组件的共享状态进行集中式的管理(读/写),也是一种组件间通信的方式,且适用于任意组件间通信。
1.是什么:
vuex 是一个 vue 的 状态管理工具,状态就是数据
大白话:vuex 是一个插件,可以帮我们**管理vue 通用的数据(多组件共享的数据)**
2.场景:
① 某个状态 在 很多个组件 来使用(个人信息)
② 多个组件 共同维护 一份数据(购物车)
3.优势:
① 共同维护一份数据,数据集中化管理
② 响应式变化
③ 操作简洁(vuex提供了一些辅助函数)
何时使用?
多个组件需要共享数据时
搭建vuex环境
-
安装vuex
npm i vuex@3 //vue2 安装3版本 vue3安装4版本 -
创建文件:
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//传入store配置项 })
vuex中的配置项
state(存放数据)
state-状态,即数据, 类似于vue组件中的data
区别:
1.data 是组件自己的数据
2.state 是所有组件共享的数据
state对象,用于存放数据
const store = new Vuex.Store({
state:{
count:0
},
}
strict(严格模式)
strict: true:开启严格模式
vuex不允许直接用*store.state.num++*这类直接修改`state`中的数据的方法来修改`state`中的值,虽然代码执行不会报错,`state`中的数据也会改变,但是后期会影响维护,这是**不规范的操作**。
2.开启严格模式后,若执行*store.state.num++*这类直接修改state中的数据时,会提醒用户报错,不配置将不会提醒
注意:上线时要关闭严格模式,不然会消耗性能
getters(存放加工state中的数据)
-
概念:当state中的数据需要经过加工后再使用时,可以使用getters加工,类似于Vue中的计算属性,区别在于,因为只能获取,不能修改,修改需要用
mutations -
基本使用:必须要有返回值,返回值就是定义该属性的值,类似计算属性(computed)
//创建并暴露store export default new Vuex.Store({ ...... getters:{ bigSum(state){ return state.sum * 10 } } }) -
组件中读取/访问数据:
$store.getters.bigSum
mutations(存放方法)
-
mutations对象,对象中存放修改 state 的方法,方法中只能有两个参数,第一个是store里面的state,第二个是this.$store.commit('函数名',参数)传的参数,只能传一个参数,需要传多个参数时,可以将参数改为对象或数组的形式传。 -
注意 :
mutations必须是同步的(便于监测数据变化,记录调试)const store = new Vuex.Store({ state:{ count:0 }, // 定义mutations mutations:{ //第一个参数是当前store的state属性,第二个数是提交调用commit传的参数 函数名(state,参数) { state.count += 参数 } } })2.组件中提交调用
mutationsthis.$store.commit('函数名',参数)
actions(存放处理异步的方法/函数)
说明: mutations 必须是同步的(便于监测数据变化,记录调试),处理异步必须使用actions,并且需要修改state中的数据时需要和mutations搭配使用,处理异步:通常是发请求
参数说明:第一个参数是context(上下文),第二个参数是$store.dispatch('方法名',参数)传入的参数
Context(上下文)
- 上下文(Context)的概念:在计算机科学中,上下文通常指的是在某一特定时间点或操作点上的环境信息或状态。在Vuex的actions中,
context就是这样一种环境信息,它包含了与store相关的所有方法和属性,使得在actions中能够访问到这些资源和能力。 - 包含的方法和属性:
commit:用于提交一个mutation,从而更改应用的状态。dispatch:用于分发一个action,可以包含异步操作。getters:用于访问store中的getter。state:直接访问store的state对象。rootState和rootGetters(在模块化的store中):用于访问根节点的state和getters。
actions: {
// 处理异步的方法
asyncChangeNum (context, num) {
// 多数时候是发送请求
setTimeout(() => {
context.commit('mutations里面的方法', num)
}, 1000)
}
}
组件中提交调用:actions
$store.dispatch('处理异步的方法',参数)
基本使用
-
初始化数据、配置
actions、配置mutations,操作文件store.js//引入Vue核心库 import Vue from 'vue' //引入Vuex import Vuex from 'vuex' //引用Vuex Vue.use(Vuex) //创建并暴露store export default new Vuex.Store({ // 开启严格模式,vuex不允许直接用store.state.属性的方法来修改state中的值, // 开启严格模式后,会提醒用户报错,不配置将不会提醒 // 注意:上线时要关闭严格模式,不然会消耗性能 strict: true, // state状态,即数据,类似于vue组件中的data // 区别: // 1.data 是组件自己的数据 // 2.state 是所有组件共享的数据 state = { sum:0 }, actions= { // 响应组件中加的动作 jia(context,value){ // console.log('actions中的jia被调用了',miniStore,value) context.commit('JIA',value) }, }, mutations = { // 执行加 JIA(state,value){ // console.log('mutations中的JIA被调用了',state,value) state.sum += value } }, }) -
组件中读取vuex中的数据:
$store.state.sum -
JS中读取vuex中的数据:
store.state.sum -
组件中修改vuex中的数据:
$store.dispatch('action中的方法名',数据)或$store.commit('mutations中的方法名',数据)备注:若没有网络请求或其他业务逻辑,组件中也可以越过actions,即不写
dispatch,直接编写commit
四个map方法的使用
mapState方法:
用于帮助我们映射state中的数据为计算属性
computed: {
//借助mapState生成计算属性:Vuex中state的属性名、school、subject(对象写法,改名)
...mapState({组件使用的属性名:'Vuex中state的属性名',school:'school',subject:'subject'}),
//借助mapState生成计算属性:Vuex中state的属性名、school、subject(数组写法)
...mapState(['Vuex中state的属性名','school','subject']),
},
mapGetters方法:
用于帮助我们映射getters中的数据为计算属性
computed: {
//借助mapGetters生成计算属性:bigSum(对象写法)
...mapGetters({bigSum:'bigSum'}),
//借助mapGetters生成计算属性:bigSum(数组写法)
...mapGetters(['bigSum'])
},
mapMutations方法:
用于帮助我们生成与mutations对话的方法,即:生成包含$store.commit(xxx)的函数
methods:{
//靠mapActions生成:Vuex中mutations的方法名、decrement(对象写法)
...mapMutations({组件使用的方法名:'Vuex中mutations的方法名',decrement:'JIAN'}),
//靠mapMutations生成:Vuex中mutations的方法名、JIAN(数组写法)
...mapMutations(['Vuex中state的方法名','JIAN']),
}
备注:mapActions与mapMutations使用时,若需要传递参数需要:在模板中绑定事件时传递好参数,否则参数是事件对象。
mapActions方法:
用于帮助我们生成与actions对话的方法,即:包含$store.dispatch(xxx)的函数
methods:{
//靠mapActions生成:incrementOdd、incrementWait(对象写法)
...mapActions({incrementOdd:'jiaOdd',incrementWait:'jiaWait'})
//靠mapActions生成:incrementOdd、incrementWait(数组写法)
...mapActions(['jiaOdd','jiaWait'])
}
四个map的注意点
mapState、mapGetters都应该放到组件的computed中,因为vuex的设计初衷是为了响应式共享数据,若放到组件的data中,vuex中的state数据将不会是响应式的。mapMutations、mapActions都放在组件的methods中
模块化
目的:让代码更好维护,让多种数据分类更加明确。维护时只需要根据所属模块来修改即可。
基本使用:
-
模块拆分
-
创建模块:
src/store/modules/user.js,根据需求创建模块//例: 创建用户模块 const state = { userInfo: { name: 'kaka', age: 20 } } const mutations = {} const actions = {} const getters = {} const users = { state, mutations, actions, getters } // 导出模块 export default users -
引入模块并配置
// 引入用户模块 import users from '@/store/modules/user' // 引入设置模块 import settings from '@/store/modules/settings' const store = new Vuex.Store({ ...... //配置模块 modules: { users, settings } })
组件使用模块中的数据和方法
注意:尽管已经分模块了,但其实子模块的状态,还是会挂到根级别的state 中,属性名就是模块名

组件获取子模块中 state 中的数据
① 直接通过模块名访问 $store.state.模块名.xxx
② 通过 mapState 映射:
默认根级别的映射 mapState(['xxx'])
子模块的映射 mapstate('模块名',['xxx']),需要开启命名空间(模块中配置 namespaced: true)
组件获取子模块中 getters 中的数据
① 直接通过模块名访问 $store.getters['模块名/xxx']
② 通过 mapGetters 映射:
默认根级别的映射 mapGetters(['xxx'])
子模块的映射 mapGetters('模块名',「'xxx'])-需要开启命名空间
组件调用子模块中 mutation方法
注意:默认模块中的 mutation 和 actions 会被挂载到全局,需要开启命名空间,才会挂载到子模块。
① 直接通过 store 调用 $store.commit('模块名/xxx',额外参数)
② 通过 mapMutations 映射:
默认根级别的映射 mapMutations(['xxx'])
子模块的映射 mapMutations('模块名',['xxx'])-需要开启命名空间组件
组件调用子模块中 action方法
注意 : ** 默认模块中的** mutation 和 actions 会被挂载到全局,需要开启命名空间,才会挂载到子模块。
① 直接通过 store 调用 $store.dispatch('模块名/xxx',额外参数)
② 通过 mapActions 映射
默认根级别的映射 mapActions(['xxx'])
子模块的映射 mapActions('模块名',['xxx'])-需要开启命名空间
模块化+命名空间
-
目的:让代码更好维护,让多种数据分类更加明确。
-
修改
store.jsconst countAbout = { namespaced:true,//开启命名空间 state:{x:1}, mutations: { ... }, actions: { ... }, getters: { bigSum(state){ return state.sum * 10 } } } const personAbout = { namespaced:true,//开启命名空间 state:{ ... }, mutations: { ... }, actions: { ... } } const store = new Vuex.Store({ modules: { countAbout, personAbout } }) -
开启命名空间后,组件中读取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'}),