在Options API中,我们可以通过watch选项来侦听data或者props的数据变化,当数据变化时执行某一些操作。 在Composition API中,我们可以使用watchEffect和watch来完成响应式数据的侦听。 watchEffect用于自动收集响应式数据的依赖,需要手动指定侦听的数据源。

侦听数据的变化

案例:
watchEffect传入的函数会被立即执行一次,并且在执行的过程中会收集依赖; 其次,只有收集的依赖发生变化时,watchEffect传入的函数才会再次执行;
<template>
  <div>
    <h2>{{name}}-{{age}}</h2>
    <button @click="changeName">修改name</button>
    <button @click="changeAge">修改age</button>
  </div>
</template>

<script>
  import { ref, watchEffect } from 'vue';

  export default {
    setup() {
      // watchEffect: 自动收集响应式的依赖
      const name = ref("why");
      const age = ref(18);

      const changeName = () => name.value = "kobe"
      const changeAge = () => age.value++

      watchEffect(() => {
        console.log("name:", name.value, "age:", age.value);
      });

      return {
        name,
        age,
        changeName,
        changeAge
      }
    }
  }
</script>

停止侦听

如果在某些情况下希望停止侦听,这个时候我们可以获取watchEffect的返回值函数,调用该函数即可。
 const stop = watchEffect(() => {
        console.log("name:", name.value, "age:", age.value);
      });

      const changeName = () => name.value = "kobe"
      const changeAge = () => {
        age.value++;
        if (age.value > 25) {
          stop();
        }
      }
比如在上面的案例中,当age达到25的时候就停止侦听。

清除副作用

在开发中我们需要在侦听函数中执行网络请求,但是在网络请求还没有达到的时候,停止了侦听器,或者侦听器/侦听函数被再次执行了。 那么上一次的网络请求应该被取消掉,这个时候我们就可以清除上一次的副作用;
在给watchEffect传入的函数被回调时,其实可以获取到一个参数:onInvalidate
当  副作用即将重新执行 或者 侦听器被停止 时会执行该函数传入的回调函数,此时我们可以在传入的回调函数中,执行一些清除工作。

  const stop = watchEffect((onInvalidate) => {
        const timer = setTimeout(() => {
          console.log("网络请求成功~");
        }, 2000)

        // 根据name和age两个变量发送网络请求
        onInvalidate(() => {
          // 在这个函数中清除额外的副作用
          // request.cancel()
          clearTimeout(timer);
          console.log("onInvalidate");
        })
        console.log("name:", name.value, "age:", age.value);
      });

setup中使用ref

在setup中如何使用ref获取元素或组件?
其实非常简单,我们只需要定义一个ref对象,绑定到元素或者组件的ref属性上即可。

这里也可以用生命周期函数mounted来检测是否能正确获取到对应的dom元素。不过这里侦听函数会立即执行一次,所以先打印一个null值,后面等页面挂载完成了,搜集的依赖就再次被回调执行一次,打印真正的dom对象。

 默认情况下,组件的更新会在副作用函数执行之前。

调整watchEffect执行时机

如果我们希望在第一次的时候就打印出来对应的元素呢?
这个时候就需要改变副作用函数的执行时机:默认值是pre,在元素挂载或者更新之前执行。
所以会先打印出来一个null,当依赖的title发生改变时,就会再次执行一次,打印出元素;

 watchEffect(() => {
        console.log(title.value);
      }, {
        flush: "post" //  获取组件更新完成之后的DOM
      })
flush 选项还接受sync,这将强制效果始终同步触发。然而这是低效的,应该很少需要。

 

Logo

前往低代码交流专区

更多推荐