VUE3的watchEffect使用


VUE3的watchEffect使用

VUE2.0大家都是是用过watch,可以监听某个值的变更,可以做一些相应的事件处理。VUE3.0出来一个watchEffect的东西,我们一起看下这个api有什么用途。

与watch有什么区别?

我们先来看一个简单watch的例子

<script lang="ts">
import {
  defineComponent, watch, ref,
} from 'vue';

export default defineComponent({
  setup() {
    const count = ref(0);
    watch(count, (val, oldVal) => {
      console.log(val, oldVal);
    });

    setTimeout(() => {
      count.value += 1; // 当值改变时执行
    }, 1000);
  }
});
</script>

再来看一个watchEffect的简单例子

<script lang="ts">
import {
  defineComponent, watchEffect, ref,
} from 'vue';

export default defineComponent({
  setup() {
    const count = ref(0);
    watchEffect(() => {
      console.log(count.value); // 初始化时会执行一次
    });

    setTimeout(() => {
      count.value += 1; // 值变化时又执行了一次
    }, 1000);
  }
});
</script>

通过两个简单的例子,我们可以看得出,watch和watchEffect还是有一些区别的

  • watchEffect会自动的收集依赖,而watch是明确的指定监听某个变量
  • watch可以获取到新值和旧值,watchEffect则只能取到最新的
  • watchEffect会在初始化的时候执行一次,类似computed

与compute有什么区别?

同样,我们先来看一个例子

<template>
  {{sayHello}}
</template>

<script lang="ts">
import {
  defineComponent, watchEffect, ref, computed,
} from 'vue';

export default defineComponent({
  setup() {
    const count = ref(0);
    watchEffect(() => {
      console.log(count.value);
    });

    setTimeout(() => {
      count.value = 20;
    }, 1000);

    const name = ref('thomaskwun');
    const sayHello = computed(() => {
      console.log('computed', count.value);
      return `我是${name.value},${count.value}岁`;
    });
    return {
      sayHello,
    };
  },
});
</script>

computed和watchEffect相同的地方是会自动收集依赖,在值更新时会触发回调,会初始化调用一次。
但是在触发初始化的时机是不一样的,如果computed的值没有被使用,是不会触发回调的,只有在该值被使用的时候才会触发回调,但watchEffect是在setup的时候就会初始化。
根据他们的差异,我们可以在不同的业务场景下选择合适的处理方法。

watchEffect的使用

注意事项

如果watchEffect涉及到dom或者ref的操作,需要在onMounted生命周期里调用

停止监听

<script lang="ts">
import {
  defineComponent, watchEffect, ref,
} from 'vue';

export default defineComponent({
  setup() {
    const count = ref(0);
    const myWatch = watchEffect(() => {
      console.log(count.value);
    });

    setTimeout(() => {
      console.log('change');
      count.value = 20;
    }, 1000);

    myWatch();
  },
});
</script>

如果是在setup的生命周期里声明的watchEffect,在组件销毁的时候是会默认清除监听,也可以再次调用watchEffect显式停止监听。

清除副作用

const count = ref(0);

const stop = watchEffect(onInvalidate => {
  const token = asyncOperate(count.value);
  onInvalidate(() => {  // 消除上次的副作用
    token.cancel();
  })
}

watchEffect进阶

const count = ref(0);

const stop = watchEffect(onInvalidate => {
  const token = asyncOperate(count.value);
  onInvalidate(() => {  // 消除上次的副作用
    token.cancel();
  })
}, {
  flush: "sync",     // 副作用的调度机制 sync, pre, post
  onTrack: e => {    // 调试用: 追踪的信息
    console.log(e);
  },
  onTrigger: e => {  // 调试用:响应式信息
    console.log(e);
  },
})

// 如副作用中设计到DOM的操作和ref的获取,需要放到mounted周期中执行
onMounted(() => {
  watchEffect(() => { // .. 操作dom或ref等 })
})

参考资料

https://www.yuque.com/atomjaylee/fe/sm5bst
https://segmentfault.com/a/1190000023669309


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM