为什么vue3计算属性get数组与对象,当改变时,无法执行set?

  • 48

vue3计算属性当get数组与对象,当改变时,无法执行set,经尝试只有基本类型才能触发set,这是为什么。

const count = ref([1, 2, 3]);
const plusOne = computed({
  get: () => count.value,
  set: val => {
  console.log('++++++++++');
  count.value = val;
  }
});
console.log(plusOne.value.push(4));
回复
阅读 1.8k
3 个回答
Runningfyy
  • 1.3k
✓ 已被采纳

这个问题和我之前回答的问题答案是差不多的。
https://segmentfault.com/q/10...

const count = ref([1, 2, 3]);
const plusOne = computed({
  get: () => count.value,
  set: val => {
  console.log('++++++++++');
  count.value = val;
  }
});
console.log(plusOne.value.push(4));

为什么这么写,不打印'++++' 因为取plusOne.value值的时候调用get进行依赖收集,只收集了'count.value'。没有搜集count.value.length

为什么@Meathill 楼下的回答有响应式,因为他用了模板,模板收集了length,push引发lenth变化,视图会更新,但是'+++++'还是不会打印
有模板相当于

//...
//有模板类似添加了下面这个effect
 effect(()=>{
                if(plusOne.value.length){
                    console.log('渲染视图')
                }
            })
console.log(plusOne.value.push(4));  

如果想'++++'打印 怎么做?
plusOne.value = [1,2,3,4]

我不知道你的模版怎么写的,不过我测试的结果并不支持你的说法,参考:

Vue SFC Playground

非马梦衢
  • 135

你的这种写法与computed计算属性毫无关系,只会触发 watch

computed() infers its type based on the getter's return value.

computed() 根据你的 getter 来判断监听的对象和类型,你的demo里面监听的是 count.value,也就是 [1, 2, 3],那么对应的 setter 也只会在你对 [1, 2, 3] 整体做重新赋值的时候才会被触发;也就是说你的demo里的 plusOne.value.push(4) 并不是一个对 count.value 的赋值操作,仅仅是数组内部的数据更新,这个更新会改变 plusOne,但并不会触发 plusOneset 操作。

如果你把 plusOne.value.push(4) 改成一个对象的整体赋值操作,比如 plusOne.value = [1, 2, 3, 4],这样是会触发set操作的。

const count = ref([1, 2, 3])
const plusOne = computed({
  get: () => count.value,
  set: (val) => {
    console.log('++++++++++')
    count.value = val
    console.log('[debug-ts] count.value', count.value)
  },
})

function createService(e: PointerEvent) {
  plusOne.value = [1, 2, 3, 4]
  console.log('[debug-ts] kasmdkas', plusOne.value)
  console.log('[debug-ts]', e)
}

image.png

从上图可以看到,plusOne.value = [1, 2, 3, 4] 对 plusOne 重新赋值了,所以computed计算属性 write 的动作就被激活了,打印顺序也印证了。

宣传栏