Vue3之watch和watchEffect实战总结

watchwatchEffect都是vue3中的监听器,但是在写法和使用上是有区别的,主要是介绍一下watchwatchEffect的使用方法以及他们之间的区别。

watch 的工作原理:侦听特定的数据源,并在回调函数中执行副作用。它默认是惰性的——只有当被侦听的源发生变化时才执行回调,不过,可以通过配置 immediate 为 true 来指定初始时立即执行第一次。可以通过配置 deep 为 true,来指定深度监视

immdiate: 默认情况下,侦听器需要 data 后面值改变了才会生效,若需要侦听器一进入页面就生效,那就需要使用 immediate

deep: 默认情况下,侦听器只会监听数据本身的改变,若要进行深度监听,那就需要使用 deep。 immediate 和 deep 配置在第三个参数对象里

第一个参数:监听谁,第二个参数:回调函数,第三个参数:配置对象

watch监听单个数据



 

监听多个数据(初始值为空,并没有进行打印)

 
 

监听一个对象--问题



 

监听对象的某一个值

 
 

遇到的坑:

1.监视reactive定义的响应式数据时:oldValue无法正确获取、强制开启了深度监视(deep配置失效)


   

2.监视reactive定义的响应式数据中某个属性时:deep配置有效


   

3.使用ref定义数组时:(触发changeArr的时候,监听不到)


   

解决方案:


   

watchEffect

watchEffect 函数的特点:

  • 优点:

    • 会自动收集依赖,不需要手动传递侦听内容——自动侦听回调函数中使用到的响应式数据。

    • 默认 immdiate 是 true,所以初始化时会立即执行。

  • 缺点:

    • 无法获得变化前的值(oldVal)。

watch() 是懒执行的:当数据源发生变化时,才会执行回调。但在某些场景中,我们希望在创建侦听器时,立即执行一遍回调。

watchEffect相当于将watch 的依赖源和回调函数合并,当任何你有用到的响应式依赖更新时,该回调函数便会重新执行。不同于 watchwatchEffect 的回调函数会被立即执行(即 { immediate: true }

简单来说,watchEffect 是 Vue3 中的一个响应式 API,它允许你监听响应式状态的变化,并在其发生变化时触发副作用函数。这个特性非常有用,在我们需要对响应式数据进行操作的时候,我们可以在监听到变化后马上做出反应。



 

watcheffect停止监听


  
 

watchEffect的副作用

什么是副作用(side effect),简单的说副作用就是执行某种操作,如对外部可变数据或变量的修改,外部接口的调用等。watchEffect的回调函数就是一个副作用函数,因为我们使用watchEffect就是侦听到依赖的变化后执行某些操作。

Vue3watchEffect侦听副作用传入的函数可以接收一个 onInvalidate 函数作为入参,用来注册清理失效时的回调

当以下情况发生时,这个失效回调会被触发:

  • 副作用即将重新执行时(即依赖的值改变)

  • 侦听器被停止 (通过显示调用返回值停止侦听,或组件被卸载时隐式调用了停止侦听)

import { watchEffect, ref } from 'vue'

const count = ref(0)
watchEffect((onInvalidate) => {
  console.log(count.value)
  onInvalidate(() => {
    console.log('执行了onInvalidate')
  })
})

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

上述代码打印的顺序为: 0 -> 执行了onInvalidate,最后执行 -> 1

分析:初始化时先打印count的值0, 然后由于定时器把count的值更新为1, 此时副作用即将重新执行,因此onInvalidate的回调函数会被触发,打印执行了onInvalidate,然后执行了副作用函数,打印count的值1

import { watchEffect, ref } from 'vue'

const count = ref(0)
const stop = watchEffect((onInvalidate) => {
  console.log(count.value)
  onInvalidate(() => {
    console.log('执行了onInvalidate')
  })
})

setTimeout(()=> {
  stop()
}, 1000)

上述代码:当我们显示执行stop函数停止侦听,此时也会触发onInvalidate的回调函数。同样,watchEffect所在的组件被卸载时会隐式调用stop函数停止侦听,故也能触发onInvalidate的回调函数。

【注意】:

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 也可以放在其他生命周期函数内

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

总结

watch

懒执行副作用——需要手动指明侦听的内容,也要指明侦听的回调。

默认 immdiate 是 false,所以初始化时不会执行,仅在侦听的源数据变更时才执行回调。

不需要有返回值。

可以获得变化前的值(oldVal)

watchEffect

自动收集依赖,不需要手动传递侦听内容——自动侦听回调函数中使用到的响应式数据

默认 immdiate 是 true,所以初始化时会立即执行,同时源数据变更时也会执行回调。

不需要有返回值。

无法获得变化前的值(oldVal)

你可能感兴趣的:(Vue3,vue.js,前端,javascript)