Vue.js中ES6类关联计算属性的响应性问题咨询
问题原因与解决方案
嘿,这个问题其实是因为你对计算属性的setter触发逻辑理解有点偏差~
为什么setter没被调用?
你现在是直接修改localClass返回的CustomClass实例的内部属性selected,但计算属性的setter只有在你给localClass本身重新赋值的时候才会触发,比如执行this.localClass = 新的实例这种操作。
打个比方:localClass就像一个指向customClass实例的指针,你现在只是修改了指针指向的对象里的内容,指针本身没动,Vue自然检测不到这个变化去调用setter。
两种可行的解决方案
方案1:让CustomClass实例的属性变成响应式,用watch监听变化
如果你的核心需求是监听selected属性的变化,没必要死磕计算属性的setter。可以先确保customClass的属性是响应式的,然后用watch来处理变化:
props: ['customClass'], created() { // Vue 2写法:把customClass转为响应式对象 this.customClass = Vue.observable(this.customClass); // Vue 3写法: // this.customClass = reactive(this.customClass); }, watch: { 'localClass.selected'(newVal) { console.log("changed: selected is now", newVal); // 这里写你原来想在setter里执行的逻辑 } }, computed: { localClass: { get() { return this.customClass }, set(value) { console.log("localClass被重新赋值了"); // 若需要同步到父组件,可触发自定义事件 this.$emit('update:customClass', value); } } }
这样修改this.localClass.selected = true时,Vue能检测到属性变化,watch回调就会执行。
方案2:通过重新赋值触发计算属性setter
如果你一定要用计算属性的setter,那得把修改内部属性的操作改成替换整个实例:
props: ['customClass'], computed: { localClass: { get() { return this.customClass }, set(value) { console.log("changed"); // 同步新实例到父组件(按需使用) this.$emit('update:customClass', value); } } }, methods: { setSelected(newVal) { // 创建新实例并复制原有属性,修改目标值 const newCustomClass = new CustomClass(); Object.assign(newCustomClass, this.customClass); newCustomClass.selected = newVal; // 赋值新实例触发setter this.localClass = newCustomClass; } }
之后调用this.setSelected(true),就能触发setter了。
总结一下
计算属性的setter是为替换整个值设计的,不是用来监听内部属性变化的。如果要处理对象内部的属性更新,watch或者让对象变成响应式是更合适的选择~
内容的提问来源于stack exchange,提问作者stefano capra
相关产品推荐
相关产品推荐

