vue 中的watch与computed

135 阅读2分钟

在视频里www.bilibili.com/video/BV1SZ…,感觉他的computed实现的不太对劲,就做了个测试.以下在chrome上进行的测试

视频中的做法

<script src="https://unpkg.com/vue@next"></script>
<script>
  const { watchEffect,ref ,reactive} = Vue;
  let r;
  let state=reactive({a:0});
  function computed(getter){
    let result=ref(0);
    watchEffect(()=>result.value=getter());
    return result;
  }
  r=computed(()=>{
    console.log("inside called",state.a);
    return state.a+1;
  })
​
  state.a=114;//check if inside called
  console.log(".....end......",);
  // console.log(r.value);
</script>

这里computed直接使用了watchEffect了,逻辑和我之前理解的不一样.computed里面的依赖发生改变的时候,函数不执行,而在获取computed的结果时查看缓存,或者再进行结果计算,这里直接依赖改变就执行watch,就相当于watch给一个固定值赋值罢了,这作者偷懒了.(可能是为了简化).

上面代码输出结果

TestForComputed.html:12 inside called 0
TestForComputed.html:18 .....end......
TestForComputed.html:12 inside called 114

符合预期,watchEffect首先执行一次,之后改变了state.a,再执行一次,只是没想到vue的watchEffect原码中响应式的时候可能是是使用微任务执行的?(也可能是又开了个宏任务,反正不是同步的)watchEffect里面的函数再次触发时竟在end后面.

源码中的效果 computed

<script src="https://unpkg.com/vue@next"></script>
<script>
  const { watchEffect,ref ,computed,reactive} = Vue;
  let r;
  let state=reactive({a:0});
  // function computed(getter){
  //   let result=ref();
  //   watchEffect(()=>result.value=getter());
  //   return result;
  // }
  r=computed(()=>{
    console.log("inside called",state.a);
    return state.a+1;
  })
​
  state.a=114;//check if inside called
  // console.log(r.value);
  console.log(".....end......",);
</script>
TestForComputed.html:18 .....end......

这里state.a依赖改变,没有触发computed里面的函数.(等到要使用r的时候才调用)

倒数第二行注释取消后如下

result

TestForComputed.html:12 inside called 114
TestForComputed.html:17 115
TestForComputed.html:18 .....end......

首先需要r,所以computed计算获得值,所以打印了"inside called",之后打印computed的计算结果,最后结束.

所以视频里应该是为了课程连贯简化了computed的实现.

所以我的理解是

  • watch 偏向于一个值改变去执行一个函数,所以是立即触发的
  • computed 偏向于利用依赖多个值来计算最后的结果,所以类似于懒加载,到获取的时候再去利用依赖计算 仅是自己观点,如有错误,多多包涵.仅是自己观点,如有错误,多多包涵.

ps:附上watch的使用

watch :watch( ( )=> state.count , ( newValue , oldValue ) => {} )

source : state.count , callback , define a source that can be a function that returns something, and another callback.

if the result of source has not changed the callabck would not be called