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
}
}
关键点回顾
- 核心职责划分 :
state存数据、mutations同步改数据(唯一入口)、actions处理异步后调mutations、getters计算派生数据、modules拆分复杂store。 - 核心规则 :修改
state必须通过mutations,异步逻辑必须写在actions里,禁止直接修改state。 - 模块化技巧 :复杂应用一定要给模块加
namespaced: true,避免mutation/action命名冲突,便于维护。