Vuex Store实例中`state`、`mutations`、`actions`、`getters`、`modules`这几个核心配置项的区别

bash 复制代码
// 创建store实例
const store = new Vuex.Store({
  state: {
    // ...
  },
  mutations: {
    // ...
  },
  actions: {
    // ...
  },
  getters: {
    // ...
  },
  modules: {
    // ...
  }
})

// 在app.js中注入store
App({
  onLaunch: function () {
    this.$store = store
  }
}) store实例几个方法有什么区别,用法怎么区分

这些配置项是Vuex实现全局状态管理的核心,各自承担明确的职责,下面我会用通俗易懂的方式讲解每个项的作用、特点和用法,并对比它们的核心区别。


1. state - 全局状态的"仓库"

核心作用

存放整个应用的全局共享数据 ,类似Vue组件中的data,但作用域是全局的(所有组件都能访问)。

核心特点

  • 响应式:state数据变化时,依赖它的组件会自动更新
  • 规范要求:不能直接修改 (直接修改会跳过Vuex的状态追踪,调试工具无法监控),必须通过mutations修改

用法示例

javascript 复制代码
const store = new Vuex.Store({
  state: {
    count: 0,       // 全局计数
    userInfo: null  // 全局用户信息
  }
})

// 组件中获取state的两种方式
// 方式1:直接通过$store访问
this.$store.state.count // 输出 0

// 方式2:mapState辅助函数(推荐,简化代码)
import { mapState } from 'vuex'
export default {
  computed: {
    // 把state中的count、userInfo映射为组件的计算属性
    ...mapState(['count', 'userInfo'])
  }
}

2. mutations - 修改state的"唯一入口"

核心作用

唯一能修改state的地方 ,负责同步更新state数据。

核心特点

  • 必须是同步函数(异步操作会导致Vuex调试工具无法追踪状态变化)
  • 只能通过store.commit()触发,不能直接调用mutation函数

用法示例

javascript 复制代码
const store = new Vuex.Store({
  state: { count: 0 },
  mutations: {
    // 定义mutation:第一个参数固定是state,第二个是载荷(payload,传入的参数)
    increment(state) {
      state.count++ // 直接修改state(仅允许在mutation中做这件事)
    },
    // 带参数的mutation
    incrementBy(state, num) {
      state.count += num
    }
  }
})

// 组件中触发mutation的两种方式
// 方式1:直接commit
this.$store.commit('increment')       // count变为1
this.$store.commit('incrementBy', 5)  // count变为6

// 方式2:mapMutations辅助函数
import { mapMutations } from 'vuex'
export default {
  methods: {
    ...mapMutations(['increment', 'incrementBy']),
    handleClick() {
      this.increment()        // 直接调用
      this.incrementBy(5)     // 传参调用
    }
  }
}

3. actions - 处理异步逻辑的"中间层"

核心作用

处理异步操作 (比如接口请求、定时器、Promise),异步操作完成后,再提交mutation修改state。

核心特点

  • 可以是异步函数(支持async/await)
  • 不能直接修改state,必须通过commit调用mutation
  • 第一个参数是context(上下文对象,包含commit/state/getters等)
  • 通过store.dispatch()触发

用法示例

javascript 复制代码
const store = new Vuex.Store({
  state: { count: 0 },
  mutations: {
    increment(state) { state.count++ }
  },
  actions: {
    // 异步action:模拟接口请求后修改count
    incrementAsync(context) {
      // 异步操作(比如定时器/接口请求)
      setTimeout(() => {
        context.commit('increment') // 异步完成后,提交mutation
      }, 1000)
    },
    // 简化写法:解构context,直接用commit
    incrementAsyncBy({ commit }, num) {
      return new Promise((resolve) => {
        setTimeout(() => {
          commit('incrementBy', num)
          resolve() // 支持Promise链式调用
        }, 1000)
      })
    }
  }
})

// 组件中触发action的两种方式
// 方式1:直接dispatch
this.$store.dispatch('incrementAsync') // 1秒后count+1

// 方式2:mapActions辅助函数
import { mapActions } from 'vuex'
export default {
  methods: {
    ...mapActions(['incrementAsync', 'incrementAsyncBy']),
    handleAsyncClick() {
      this.incrementAsync()
      this.incrementAsyncBy(5).then(() => {
        console.log('异步操作完成')
      })
    }
  }
}

4. getters - 对state数据的"计算/过滤"

核心作用

类似Vue组件中的computed,对state中的数据进行派生、过滤、计算,并缓存结果(只有依赖的state变化时才重新计算)。

核心特点

  • 基于state派生,不修改原state
  • 支持接收其他getters作为第二个参数
  • 可以返回函数,实现"带参数的getter"

用法示例

javascript 复制代码
const store = new Vuex.Store({
  state: {
    list: [1, 2, 3, 4, 5, 6]
  },
  getters: {
    // 过滤偶数
    evenList: (state) => state.list.filter(item => item % 2 === 0), // [2,4,6]
    // 依赖其他getters
    evenListLength: (state, getters) => getters.evenList.length,    // 3
    // 带参数的getter(返回函数)
    getNumById: (state) => (id) => state.list.find(item => item === id)
  }
})

// 组件中使用getters的两种方式
// 方式1:直接通过$store.getters访问
this.$store.getters.evenList       // [2,4,6]
this.$store.getters.getNumById(3)  // 3

// 方式2:mapGetters辅助函数
import { mapGetters } from 'vuex'
export default {
  computed: {
    ...mapGetters(['evenList', 'evenListLength']),
    // 重命名(避免冲突)
    ...mapGetters({ listLen: 'evenListLength' })
  }
}

5. modules - 拆分复杂store的"模块化工具"

核心作用

当应用规模大时,state/mutations/actions会变得臃肿,modules可以将store拆分为多个独立模块,每个模块拥有自己的state/mutations/actions/getters

核心特点

  • 模块内的state是局部的,需通过store.state.模块名访问
  • 默认情况下,模块内的mutations/actions是全局的(可通过namespaced: true开启命名空间,避免冲突)

用法示例

javascript 复制代码
// 定义user模块(开启命名空间)
const userModule = {
  namespaced: true, // 开启命名空间,避免和其他模块冲突
  state: { name: '张三', age: 20 },
  mutations: {
    updateName(state, newName) { state.name = newName }
  },
  actions: {
    updateNameAsync({ commit }, newName) {
      setTimeout(() => commit('updateName', newName), 1000)
    }
  }
}

// 创建store,注册模块
const store = new Vuex.Store({
  modules: {
    user: userModule, // 注册user模块
    count: { /* 另一个模块 */ }
  }
})

// 组件中使用模块内容
// 1. 获取模块state
this.$store.state.user.name // 张三

// 2. 触发带命名空间的mutation/action
this.$store.commit('user/updateName', '李四') // 格式:模块名/mutation名
this.$store.dispatch('user/updateNameAsync', '王五')

// 3. map辅助函数(指定命名空间)
import { mapMutations } from 'vuex'
export default {
  methods: {
    ...mapMutations('user', ['updateName']) // 绑定user模块的updateName
  }
}

关键点回顾

  1. 核心职责划分state存数据、mutations同步改数据(唯一入口)、actions处理异步后调mutationsgetters计算派生数据、modules拆分复杂store。
  2. 核心规则 :修改state必须通过mutations,异步逻辑必须写在actions里,禁止直接修改state
  3. 模块化技巧 :复杂应用一定要给模块加namespaced: true,避免mutation/action命名冲突,便于维护。
相关推荐
GIS之路1 小时前
ArcGIS Pro 中的 Notebooks 入门
前端
IT_陈寒3 小时前
React状态管理终极对决:Redux vs Context API谁更胜一筹?
前端·人工智能·后端
lemon_yyds3 小时前
《vue 2 升级vue3 父组件 子组件 传值: value 和 v-model
vue.js
Kagol4 小时前
TinyVue 支持 Skills 啦!现在你可以让 AI 使用 TinyVue 组件搭建项目
前端·agent·ai编程
柳杉4 小时前
从零打造 AI 全球趋势监测大屏
前端·javascript·aigc
simple_lau4 小时前
Cursor配置MasterGo MCP:一键读取设计稿生成高还原度前端代码
前端·javascript·vue.js
睡不着先生4 小时前
如何设计一个真正可扩展的表单生成器?
前端·javascript·vue.js
天蓝色的鱼鱼4 小时前
模块化与组件化:90%的前端开发者都没搞懂的本质区别
前端·架构·代码规范
明君879974 小时前
Flutter 如何给图片添加多行文字水印
前端·flutter
进击的尘埃4 小时前
AI 代码审查工具链搭建:用 AST 解析 + LLM 实现自动化 Code Review 的前端工程方案
javascript