You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为什么Nuxt运行时会报Vuex在mutation外修改存储状态的错误

问题描述
  • 我正在使用Nuxt
  • 我有一个简单的Drawer.vue组件
  • 用户完成登录操作后,我尝试展示带有抽屉的页面
  • 若登录成功,auth中间件会通过后端/me接口获取抽屉所需的菜单列表
  • 我目前遇到Vuex报错,我确认过自己没有在mutation处理函数外主动修改Vuex存储的状态

报错信息

Error: [vuex] do not mutate vuex store state outside mutation handlers.
    at assert (vuex.esm.js?2f62:135)
    at Vue.store._vm.$watch.deep (vuex.esm.js?2f62:893)
    at invokeWithErrorHandling (vue.runtime.esm.js?2b0e:1863)
    at Watcher.run (vue.runtime.esm.js?2b0e:4584)
    at Watcher.update (vue.runtime.esm.js?2b0e:4558)
    at Dep.notify (vue.runtime.esm.js?2b0e:730)
    at Object.reactiveSetter [as items] (vue.runtime.esm.js?2b0e:1055)
    at eval (Drawer.vue?c84c:43)
    at Array.filter (<anonymous>)
    at VueComponent.flatFilter (Drawer.vue?c84c:40)

相关代码

Drawer.vue

<template>
  <div>
    {{ computedItems }}
  </div>
</template>

<script>
import { mapGetters } from 'vuex'
export default {
  name: 'DashboardCoreDrawer',

  data: () => ({
    menuFiltered: [],
    defaultMenu: [
      {
        icon: 'mdi-view-dashboard',
        title: 'Dashboard',
        to: '/',
        visible: 1,
      },
    ],
  }),

  computed: {
    ...mapGetters(['menuUser']),

    computedItems() {
      return this.menuFiltered
    },
  },

  watch: {
    menuUser(newValue) {
      this.menuFiltered = this.filterItems(newValue)
    },
  },

  methods: {
    flatFilter(nestedProp, compareKey, compareId, arr) {
      return arr.filter((o) => {
        const keep = o[compareKey] !== compareId
        if (keep && o[nestedProp]) {
          o[nestedProp] = this.flatFilter(
            nestedProp,
            compareKey,
            compareId,
            o[nestedProp]
          )
        }
        return keep
      })
    },
    filterItems(arr) {
      const items = [...arr]
      const res = this.flatFilter('items', 'visible', 0, items)
      return res
    },
  },
}
</script>

Nuxt store目录下index.js

export const getters = {
  menuUser(state) {
    return state.auth.user?.menu || []
  },
}

问题原因

你用[...arr]做的是浅拷贝,仅拷贝了数组的第一层引用,数组内部嵌套的菜单对象还是直接指向Vuex store里的原始数据。在flatFilter方法中你直接修改了o[nestedProp],也就是直接修改了Vuex store中存储的菜单对象的items属性,因此触发了报错。

解决方案

修改filterItems方法,对传入的菜单数组做深拷贝,切断和Vuex原数据的引用关联即可:

filterItems(arr) {
  // 深拷贝菜单数组,避免修改Vuex原数据
  const items = JSON.parse(JSON.stringify(arr))
  const res = this.flatFilter('items', 'visible', 0, items)
  return res
}

如果你的菜单对象中包含函数、Symbol等JSON不支持的数据类型,可以改用lodash的cloneDeep方法做深拷贝。


内容的提问来源于stack exchange,提问作者Luiz Alves

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 00:42:00