严格模式 #
什么是严格模式? #
严格模式下,任何对 Vuex 状态的变更如果不是由 mutation 函数引起的,将会抛出错误。这确保了所有状态变更都能被调试工具追踪。
开启严格模式 #
javascript
import { createStore } from 'vuex'
const store = createStore({
strict: true, // 开启严格模式
state: {
count: 0
},
mutations: {
INCREMENT(state) {
state.count++
}
}
})
开发环境配置 #
推荐只在开发环境开启严格模式:
javascript
const store = createStore({
strict: process.env.NODE_ENV !== 'production'
})
或使用动态配置:
javascript
const store = createStore({
// ...
})
// 动态设置
if (process.env.NODE_ENV === 'development') {
store.strict = true
}
严格模式的限制 #
允许的操作 #
javascript
// 通过 mutation 修改状态 - 正确
this.$store.commit('INCREMENT')
// 在 mutation 内部修改状态 - 正确
mutations: {
INCREMENT(state) {
state.count++ // 允许
}
}
禁止的操作 #
javascript
// 直接修改状态 - 错误
this.$store.state.count = 10
// Error: [vuex] Do not mutate vuex store state outside mutation handlers
// 在组件中直接修改 - 错误
this.$store.state.user.name = 'John'
// 在 Action 中直接修改 - 错误
actions: {
someAction({ state }) {
state.count++ // 错误
}
}
处理表单 #
问题 #
vue
<template>
<input v-model="user.name" /> <!-- 严格模式下会报错 -->
</template>
<script>
export default {
computed: {
user() {
return this.$store.state.user
}
}
}
</script>
解决方案一:双向绑定计算属性 #
vue
<template>
<input v-model="userName" />
</template>
<script>
export default {
computed: {
userName: {
get() {
return this.$store.state.user.name
},
set(value) {
this.$store.commit('SET_USER_NAME', value)
}
}
}
}
</script>
解决方案二:局部副本 #
vue
<template>
<input v-model="localUser.name" />
<button @click="save">Save</button>
</template>
<script>
export default {
data() {
return {
localUser: { ...this.$store.state.user }
}
},
methods: {
save() {
this.$store.commit('SET_USER', this.localUser)
}
}
}
</script>
解决方案三:使用 mapFields #
javascript
// helpers/mapFields.js
export function mapFields(fields) {
const result = {}
fields.forEach(field => {
result[field] = {
get() {
return this.$store.state[field.split('/')[0]]?.[field.split('/')[1]] ||
this.$store.state[field]
},
set(value) {
this.$store.commit(`SET_${field.toUpperCase()}`, value)
}
}
})
return result
}
vue
<script>
import { mapFields } from '@/helpers/mapFields'
export default {
computed: {
...mapFields(['user/name', 'user/email'])
}
}
</script>
性能考虑 #
严格模式的性能影响 #
严格模式会深度观察状态树以检测不合规的状态变更,这会影响性能:
javascript
// 生产环境关闭
const store = createStore({
strict: process.env.NODE_ENV !== 'production'
})
深度观察 #
javascript
// 对于大型对象,严格模式可能影响性能
state: {
largeArray: [...], // 深度观察会遍历所有元素
deepObject: { ... }
}
与插件配合 #
插件中的状态修改 #
javascript
// 插件中直接修改状态会触发严格模式错误
function myPlugin(store) {
store.subscribe((mutation, state) => {
state.lastMutation = mutation.type // 错误
})
}
// 正确做法:通过 mutation
function myPlugin(store) {
store.subscribe((mutation, state) => {
store.commit('SET_LAST_MUTATION', mutation.type)
})
}
调试技巧 #
定位非法修改 #
当严格模式报错时,可以通过以下方式定位问题:
javascript
// 在开发工具中设置断点
// 或使用 console.trace
store.subscribe((mutation, state) => {
console.trace('Mutation:', mutation.type)
})
Vue DevTools #
Vue DevTools 可以帮助追踪状态变更:
- 打开 Vue DevTools
- 切换到 Vuex 标签
- 查看所有 mutation 记录
- 使用时间旅行回到之前的状态
实战配置 #
完整配置示例 #
javascript
// store/index.js
import { createStore } from 'vuex'
import user from './modules/user'
import cart from './modules/cart'
const debug = process.env.NODE_ENV !== 'production'
const store = createStore({
modules: {
user,
cart
},
strict: debug,
plugins: debug ? [
// 开发环境插件
store => {
store.subscribe((mutation, state) => {
console.log('[Vuex]', mutation.type, mutation.payload)
})
}
] : []
})
export default store
环境变量配置 #
javascript
// .env.development
VUE_APP_STRICT_MODE=true
// .env.production
VUE_APP_STRICT_MODE=false
// store/index.js
const store = createStore({
strict: process.env.VUE_APP_STRICT_MODE === 'true'
})
最佳实践 #
1. 开发环境开启 #
javascript
strict: process.env.NODE_ENV !== 'production'
2. 避免直接修改 #
javascript
// 错误
this.$store.state.user.name = 'John'
// 正确
this.$store.commit('SET_USER_NAME', 'John')
3. 表单使用局部副本 #
javascript
// 对于复杂表单,使用局部副本
data() {
return {
form: { ...this.$store.state.user }
}
}
总结 #
严格模式要点:
| 要点 | 说明 |
|---|---|
| 开启方式 | strict: true |
| 环境配置 | 只在开发环境开启 |
| 限制 | 只能通过 mutation 修改状态 |
| 表单处理 | 使用计算属性或局部副本 |
| 性能 | 生产环境关闭 |
继续学习 表单处理,了解如何在 Vuex 中处理表单。
最后更新:2026-03-28