严格模式 #

什么是严格模式? #

严格模式下,任何对 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 可以帮助追踪状态变更:

  1. 打开 Vue DevTools
  2. 切换到 Vuex 标签
  3. 查看所有 mutation 记录
  4. 使用时间旅行回到之前的状态

实战配置 #

完整配置示例 #

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