200字
Vuex
2025-10-26
2025-10-26

Vuex

概念

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

1.是什么:

vuex 是一个 vue 的 状态管理工具,状态就是数据

大白话:vuex 是一个插件,可以帮我们**管理vue 通用的数据(多组件共享的数据)**

2.场景:

① 某个状态 在 很多个组件 来使用(个人信息)

② 多个组件 共同维护 一份数据(购物车)

3.优势:

① 共同维护一份数据,数据集中化管理

响应式变化

③ 操作简洁(vuex提供了一些辅助函数)

何时使用?

​ 多个组件需要共享数据时

搭建vuex环境

  1. 安装vuex

    npm i vuex@3 //vue2 安装3版本  vue3安装4版本
    
  2. 创建文件: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
    })
    
  3. 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中的数据)

  1. 概念:当state中的数据需要经过加工后再使用时,可以使用getters加工,类似于Vue中的计算属性,区别在于,因为只能获取,不能修改,修改需要用mutations

  2. 基本使用:必须要有返回值,返回值就是定义该属性的值,类似计算属性(computed)

    //创建并暴露store
    export default new Vuex.Store({
    	......
    	getters:{
            bigSum(state){
                return state.sum * 10
            }
        }
    })
    
  3. 组件中读取/访问数据:$store.getters.bigSum

mutations(存放方法)

  1. mutations 对象,对象中存放修改 state 的方法,方法中只能有两个参数,第一个是store里面的state,第二个是this.$store.commit('函数名',参数)传的参数,只能传一个参数,需要传多个参数时,可以将参数改为对象或数组的形式传。

  2. 注意mutations 必须是同步的(便于监测数据变化,记录调试)

    const store =  new Vuex.Store({
      state:{
        count:0
      },
      // 定义mutations
      mutations:{
      //第一个参数是当前store的state属性,第二个数是提交调用commit传的参数
        函数名(state,参数) {
          state.count += 参数
        }
      }
    })
    

    2.组件中提交调用 mutations

    this.$store.commit('函数名',参数)
    

actions(存放处理异步的方法/函数)

说明: mutations 必须是同步的(便于监测数据变化,记录调试),处理异步必须使用actions,并且需要修改state中的数据时需要和mutations搭配使用,处理异步:通常是发请求

参数说明:第一个参数是context(上下文),第二个参数是$store.dispatch('方法名',参数)传入的参数

Context(上下文)

  1. 上下文(Context)的概念:在计算机科学中,上下文通常指的是在某一特定时间点或操作点上的环境信息或状态。在Vuex的actions中,context 就是这样一种环境信息,它包含了与store相关的所有方法和属性,使得在actions中能够访问到这些资源和能力。
  2. 包含的方法和属性
    • commit:用于提交一个mutation,从而更改应用的状态。
    • dispatch:用于分发一个action,可以包含异步操作。
    • getters:用于访问store中的getter。
    • state:直接访问store的state对象。
    • rootStaterootGetters(在模块化的store中):用于访问根节点的state和getters。
actions: {
    // 处理异步的方法
    asyncChangeNum (context, num) {
      // 多数时候是发送请求
      setTimeout(() => {
        context.commit('mutations里面的方法', num)
      }, 1000)
    }
  }

组件中提交调用:actions

$store.dispatch('处理异步的方法',参数)

基本使用

  1. 初始化数据、配置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
            }
    	},
    	
    })
    
  2. 组件中读取vuex中的数据:$store.state.sum

  3. JS中读取vuex中的数据:store.state.sum

  4. 组件中修改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的注意点

  1. mapStatemapGetters都应该放到组件的computed中,因为vuex的设计初衷是为了响应式共享数据,若放到组件的data中,vuex中的state数据将不会是响应式的。
  2. mapMutationsmapActions都放在组件的methods

模块化

目的:让代码更好维护,让多种数据分类更加明确。维护时只需要根据所属模块来修改即可。

基本使用:

  1. 模块拆分

  2. 创建模块: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
    
  3. 引入模块并配置

    // 引入用户模块
    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方法

注意:默认模块中的 mutationactions 会被挂载到全局,需要开启命名空间,才会挂载到子模块

① 直接通过 store 调用 $store.commit('模块名/xxx',额外参数)

② 通过 mapMutations 映射:

​ 默认根级别的映射 mapMutations(['xxx'])

​ 子模块的映射 mapMutations('模块名',['xxx'])-需要开启命名空间组件

组件调用子模块中 action方法

注意 : ** 默认模块中的** mutationactions 会被挂载到全局,需要开启命名空间,才会挂载到子模块

① 直接通过 store 调用 $store.dispatch('模块名/xxx',额外参数)
② 通过 mapActions 映射

​ 默认根级别的映射 mapActions(['xxx'])

​ 子模块的映射 mapActions('模块名',['xxx'])-需要开启命名空间

模块化+命名空间

  1. 目的:让代码更好维护,让多种数据分类更加明确。

  2. 修改store.js

    const 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
      }
    })
    
  3. 开启命名空间后,组件中读取state数据:

    //方式一:自己直接读取
    this.$store.state.personAbout.list
    //方式二:借助mapState读取:
    ...mapState('countAbout',['sum','school','subject']),
    
  4. 开启命名空间后,组件中读取getters数据:

    //方式一:自己直接读取
    this.$store.getters['personAbout/firstPersonName']
    //方式二:借助mapGetters读取:
    ...mapGetters('countAbout',['bigSum'])
    
  5. 开启命名空间后,组件中调用dispatch

    //方式一:自己直接dispatch
    this.$store.dispatch('personAbout/addPersonWang',person)
    //方式二:借助mapActions:
    ...mapActions('countAbout',{incrementOdd:'jiaOdd',incrementWait:'jiaWait'})
    
  6. 开启命名空间后,组件中调用commit

    //方式一:自己直接commit
    this.$store.commit('personAbout/ADD_PERSON',person)
    //方式二:借助mapMutations:
    ...mapMutations('countAbout',{increment:'JIA',decrement:'JIAN'}),
    
Vuex
作者
蜀枕清何
发表于
2025-10-26
License
CC BY-NC-SA 4.0

评论