为什么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
相关产品推荐
相关产品推荐

