vue3中你不知道的watch和watchEffect 侦听器

这是我参与11月更文挑战的第2天,活动详情查看:11月更文挑战

watch基本介绍

watch监听某个属性的变化,一旦发生变化,就会触发对应的回调函数执行,在里面进行一些具体的操作,从而达到事件监听的效果。里面有三个参数,下面让我们一起来学习一下。

第一个参数是:选择要监听的属性。

第二个参数是:设置的回调函数。即监听到变化时应该执行的函数 。

第三个参数是:可以设置deep (深度监听) 其值为true和false。还可以设置immediate (是否以当前值执行回调函数) 其值为true和false。

watch使用

1.监听ref定义的一个响应式数据

 import { watch, ref } from 'vue'
 setup() {
      let mes = ref('会好的')
      //第一种情况 监听ref定义的一个响应式数据
      watch(mes, (qian, hou) => {
        console.log('变化----', qian, hou)
      }, {immediate: true})
 }
复制代码

2.监听ref定义的多个响应式数据

 setup() {
      let mes = ref('会好的')
      let mess = ref('我是谁')
      //第二种情况 监听ref定义的多个响应式数据
      watch([mes,mess], (qian, hou) => {
        console.log('变化----', qian, hou)
      },{immediate:true})
 }
复制代码

3.监听reactive定义的属性,会将deep:true强制开启

setup() {
       let rea=reactive({
        name:'我是谁',
        obj:{
          salary:20
        }
      })
      //第三种情况 监听reactive定义的属性
       watch(rea,(qian,hou)=>{
        console.log('rea变化了',qian,hou)
      })
 }

复制代码

4.监听reactive定义的属性(基本数据)

setup() {
       let rea=reactive({
        name:'我是谁',
        obj:{
          salary:20
        }
      })
      //第四种情况 监听reactive定义的属性(基本数据)
      watch(()=>rea.name,(qian,hou)=>{
        console.log('名称变化===',qian,hou)
      })
 }
复制代码

5.监听reactive定义的 引用数据 (需要自己开启 deep:true深度监听)

setup() {
       let rea=reactive({
        name:'我是谁',
        obj:{
          salary:20
        }
      })
      //第五种情况 监听reactive定义的 (引用数据)
       watch([()=>rea.name,()=>rea.obj],(qian,hou)=>{
        console.log('监听reactive定义的某一些属性---',qian,hou)
      },{deep:true})
 }
复制代码

watch存在的一些问题

1.监听reactive定义的响应式数据,会强制开启深度监听(deep:true),无法获取正确的oldvalue(变化前的值)。

2.监听reactive定义的响应式数据中的某个属性(对象形式)时,不会强制开启深度监听,需要自己手动设置(deep:true)才会有效果。

watchEffect基本介绍

Vue3除了watch api,还增加了一个新的watchEffect api,下面我们一起来看看具体的用法。

watchEffect使用

会立即执行传入的一个函数,同时响应式追踪其依赖,并在其依赖变更时重新运行该函数。(有点像计算属性)

// 例子来源于(https://v3.vuejs.org/api/computed-watch-api.html#watcheffect)

import { watchEffect, ref } from 'vue'
setup () {
    const userID = ref(0)
    watchEffect(() => console.log(userID))
    setTimeout(() => {
      userID.value = 1
    }, 1000)

    /*
      * LOG
      * 0 
      * 1
    */

    return {
      userID
    }
 }
复制代码

watchEffect进阶使用

1.停止监听

当 watchEffect 在组件的 setup() 函数或生命周期钩子被调用时,侦听器会被链接到该组件的生命周期,并在组件卸载时自动停止。

在一些情况下,也可以显式调用返回值以停止侦听:

const stop = watchEffect(() => {
  /* ... */
})

// later
stop()
复制代码

2.清除副作用(onInvalidate)

有时副作用函数会执行一些异步的副作用,这些响应需要在其失效时清除 (即完成之前状态已改变了) 。所以侦听副作用传入的函数可以接收一个 onInvalidate 函数作入参,用来注册清理失效时的回调。当以下情况发生时,这个失效回调会被触发:

  • 副作用即将重新执行时
  • 侦听器被停止 (如果在 setup() 或生命周期钩子函数中使用了 watchEffect,则在组件卸载时)
watchEffect(onInvalidate => {
  const token = performAsyncOperation(id.value)
  onInvalidate(() => {
    // id has changed or watcher is stopped.
    // invalidate previously pending async operation
    token.cancel()
  })
})
复制代码

我们之所以是通过传入一个函数去注册失效回调,而不是从回调返回它,是因为返回值对于异步错误处理很重要。

在执行数据请求时,副作用函数往往是一个异步函数

const data = ref(null)
watchEffect(async onInvalidate => {
  onInvalidate(() => {
    /* ... */
  }) // 我们在Promise解析之前注册清除函数
  data.value = await fetchData(props.id)
})
复制代码

我们知道异步函数都会隐式地返回一个 Promise,但是清理函数必须要在 Promise 被 resolve 之前被注册。另外,Vue 依赖这个返回的 Promise 来自动处理 Promise 链上的潜在错误。

watch注意点

watchEffect 会在 Vue3 开发中大量使用,这里有几个注意点:

1.如果有多个负效应,不要粘合在一起,建议写多个 watchEffect

watchEffect(() => {
  setTimeout(() => console.log(a.val + 1), 1000);
  setTimeout(() => console.log(b.val + 1), 1000);
});
复制代码

这两个 setTimeout 是两个不相关的效应,不需要同时监听 a 和 b,分开写:

watchEffect(() => {
  setTimeout(() => console.log(a.val + 1), 1000);
});

watchEffect(() => {
  setTimeout(() => console.log(b.val + 1), 1000);
});
复制代码

2.watchEffect 也可以放在其他生命周期函数内

比如你的副作用函数在首次执行时就要调用 DOM,你可以把他放在 onMounted 钩子里:

onMounted(() => {
  watchEffect(() => {
    // access the DOM or template refs
  });
}
复制代码

watch和watchEffect的区别

1.watch可以访问新值和旧值,watchEffect不能访问。

2.watchEffect有副作用,DOM挂载或者更新之前就会触发,需要我们自己去清除副作用。

3.watch是惰性执行,也就是只有监听的值发生变化的时候才会执行,但是watchEffect不同,每次代码加载watchEffect都会执行。

4.watch需要指明监听的对象,也需要指明监听的回调。watchEffect不用指明监视哪一个属性,监视的回调函数中用到哪个属性,就监视哪个属性。

总结

以上就是自己对Vue3中监听api的理解,有不对的地方欢迎指出来改正。也希望看完的同学可以给一个免费的赞。以上参考文献出自Vue官方文档

猜你喜欢

转载自juejin.im/post/7032658568272691231