Vuex
概念
在Vue中实现集中式状态(数据)管理的一个Vue插件,对vue应用中多个组件的共享状态进行集中式的管理(读/写),也是一种组件间通信的方式,且适用于任意组件间通信。
1.是什么:
vuex 是一个 vue 的 状态管理工具,状态就是数据
大白话管理vue 通用的数据(多组件共享的数据)**
2.场景:
① 某个状态 在 很多个组件 来使用(个人信息)
② 多个组件 共同维护 一份数据(购物车)
3.优势:
① 共同维护一份数据,数据集中化管理
② 响应式变化
③ 操作简洁(vuex提供了一些辅助函数)
何时使用?
多个组件需要共享数据时
搭建vuex环境
-
安装vuex
Terminal window npm i vuex@3 //vue2 安装3版本 vue3安装4版本 -
创建文件:
src/store/index.js//引入Vue核心库import Vue from 'vue'//引入Vueximport Vuex from 'vuex'//应用Vuex插件Vue.use(Vuex)//准备actions对象——响应组件中用户的动作const actions = {}//准备mutations对象——修改state中的数据const mutations = {}//准备state对象——保存具体的数据const state = {}//创建并暴露storeexport default new Vuex.Store({actions,mutations,state}) -
在
main.js中创建vm时传入store配置项......//引入storeimport store from './store'......//创建vmnew 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中的数据时,会提醒用户报错,不配置将不会提醒
注意:上线时要关闭严格模式,不然会消耗性能
getters(存放加工state中的数据)
-
概念:当state中的数据需要经过加工后再使用时,可以使用getters加工,类似于Vue中的计算属性,区别在于,因为只能获取,不能修改,修改需要用
mutations -
基本使用:必须要有返回值,返回值就是定义该属性的值,类似计算属性(computed)
//创建并暴露storeexport 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},// 定义mutationsmutations:{//第一个参数是当前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'//引入Vueximport Vuex from 'vuex'//引用VuexVue.use(Vuex)//创建并暴露storeexport 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
//方式一:自己直接dispatchthis.$store.dispatch('personAbout/addPersonWang',person)//方式二:借助mapActions:...mapActions('countAbout',{incrementOdd:'jiaOdd',incrementWait:'jiaWait'}) -
开启命名空间后,组件中调用commit
//方式一:自己直接committhis.$store.commit('personAbout/ADD_PERSON',person)//方式二:借助mapMutations:...mapMutations('countAbout',{increment:'JIA',decrement:'JIAN'}),