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