为什么我的JavaScript(Vue)代码中对象属性会被标记为只读?
问题原因
你对计算属性的认知是正确的:计算属性本身的返回值(比如本次的数组)不可直接赋值,但数组内部元素的属性可修改性和计算属性没有任何关系,该报错的核心是你修改的Box对象本身被限制了属性写入权限,常见触发场景有三类:
- Vuex 严格模式限制:如果你的
boxes数组存储在Vuex的state中,且Vuex开启了严格模式strict: true,所有不在mutation中直接修改state属性的操作都会被拦截,被修改的对象属性会被标记为只读。你从计算属性拿到的Box对象是Vuex state中对象的直接引用,直接修改属性就会触发该报错。 - Box类属性定义限制:如果你在定义
Box类时,object_class属性只声明了getter方法没有对应的setter,或者通过Object.defineProperty设置了writable: false,就会导致该属性不可写入。 - 对象被主动冻结:如果在初始化
Box对象、存入boxes数组的过程中,为了优化性能调用了Object.freeze(box),冻结后的对象所有属性都不可修改、删除。
排查与修复方案
- 优先确认Vuex配置是否开启了严格模式,如果是,必须通过mutation提交修改,禁止直接修改state中的对象属性,示例代码如下:
// Vuex mutations 定义 mutations: { setBoxObjectClass(state, { box, objectClass }) { box.object_class = objectClass box.patch() } } // 业务方法调用 this.nearest_box_linked_boxes.forEach(box => { this.$store.commit('setBoxObjectClass', { box, objectClass: this.$store.state.selected_object_class }) })
- 检查
Box类的object_class属性定义,补全setter或修改writable配置为true。 - 排查初始化
Box对象的逻辑,移除不必要的Object.freeze操作。
内容的提问来源于stack exchange,提问作者afarley
相关产品推荐
相关产品推荐

