扩展使用vuex mapGetters的组件时触发非mutation修改state报错
报错原因
核心问题出在你将Vue组件构造函数直接存储到了Vue实例的响应式data属性中:
- Vue会对
data中声明的所有属性做递归响应式劫持,遍历属性关联的所有对象、原型链内容 - 你的组件构造函数绑定了原始组件的
mapGetters关联的Vuex状态引用,响应式劫持过程中会触发对Vuex状态的写入操作,违反了Vuex只能在mutation中修改状态的规则,因此抛出报错
另外你预处理组件时直接修改原始组件导出对象的data属性origin.data["origin"] = true,会污染所有该组件的实例,也存在潜在风险。
解决方案
方案1:不要将组件构造函数存到响应式data中
删除layout.vue中data内的pageView声明,改为挂载到实例的非响应式自定义属性上:
// switchView 中修改赋值逻辑 vm.$pageView = original.extend({ name: dynamicName, data: function() { return to.args || {}; } });
模板中对应调整引用:
<keep-alive :include="permittedPageViews"> <component :is="$pageView" /> </keep-alive>
方案2:冻结组件构造函数跳过响应式处理
如果需要保留pageView在data中,赋值时用Object.freeze冻结对象,Vue不会对冻结对象做响应式劫持:
vm.pageView = Object.freeze(original.extend({ name: dynamicName, data: function() { return to.args || {}; } }));
优化点:避免修改原始组件对象
不要直接修改导入的原始组件的data属性,如需加标记可以写到组件自定义选项中,或者在extend阶段注入到data:
// 预处理时不要修改origin.data,改为加自定义选项 origin.customFlag = { origin: true }
修改后即可避免响应式劫持误触Vuex状态修改的报错。
内容的提问来源于stack exchange,提问作者Dean
相关产品推荐
相关产品推荐

