一文搞懂Vue3中watch和watchEffect区别和用法!
2024-12-21 09:42 阅读(188)

前言

使用过 Vue 的小伙伴,不管时 Vue2 还是 Vue3,我相信你都用过 Vue 中的监听器。监听器的作用就和它的名字一样:用来监听某个东西是否发生变化!我们很多需求都会用到监听器 watch,但是 Vue2 和 Vue3 中的监听器的用法有些许不一样,这就让一些从 Vue2 转 Vue3 的小伙伴不太适应,所以,我们今天就来好好学一学 Vue3 中的监听器如何使用!

1. watch

watch 是 Vue 3 中用来监听特定数据源的变化(例如 ref、reactive 或计算属性)的 API。当被监听的数据源发生变化时,会触发回调函数。watch 是一种 “显式” 的方式,只有当你指定了明确的监视目标时,才会触发。

用法:

javascript
复制代码
import { ref, watch } from 'vue';

const count = ref(0);

// 监听 `count` 的变化
watch(count, (newValue, oldValue) => {
  console.log('count changed:', newValue, oldValue);
});

特点:



需要显式指定目标:你需要显式地提供要监听的响应式数据源(如 ref 或 reactive)和回调函数。



支持旧值:watch 的回调函数可以访问数据的旧值和新值,这使得它适用于需要对比前后状态的场景。



深度监听:watch 支持通过 deep 选项进行深度监听,适用于对象或数组的嵌套数据。

javascript
复制代码
const user = reactive({ name: 'John', age: 30 });

watch(user, (newValue, oldValue) => {
  console.log('User changed:', newValue, oldValue);
}, { deep: true });

监听计算属性或 getter:watch 可以用来监听计算属性或 getter 的变化。

javascript
复制代码
const doubled = computed(() => count.value * 2);

watch(doubled, (newVal, oldVal) => {
  console.log('Doubled value changed:', newVal);
});

延迟执行:默认情况下,watch 在响应式数据源发生变化时异步触发回调,可以通过 immediate: true 让它在创建时立即执行一次回调。


javascript
复制代码
watch(count, (newValue, oldValue) => {
  console.log('Count changed:', newValue, oldValue);
}, { immediate: true });

使用场景:


监听特定的变化:当你需要监听某个数据源的变化并在变化时执行某个副作用。

旧值和新值对比:当你需要在数据变化时访问前后的值。

深度监听:当你需要监听嵌套的对象或数组。


2. watchEffect

watchEffect 是一种更加自动化的方式,适用于你希望自动响应 当前作用域中的所有响应式数据变化。它会自动追踪所访问的响应式数据,并在这些数据变化时重新执行函数。

用法:

javascript
复制代码
import { ref, watchEffect } from 'vue';

const count = ref(0);

// watchEffect 会自动追踪 count 的变化
watchEffect(() => {
  console.log('count changed:', count.value);
});

特点:


自动追踪依赖:watchEffect 不需要显式指定要监听的响应式数据源,它会自动追踪在函数内访问的所有响应式数据,随这些数据变化而自动执行。

不需要旧值和新值:watchEffect 不提供旧值和新值,它只是重新执行整个副作用函数。

立即执行:watchEffect 默认在创建时立即执行一次回调,不需要像 watch 那样配置 immediate: true。


使用场景:


无需手动指定依赖:当你想要自动监听当前作用域内所有响应式数据的变化,而无需显式声明依赖。

副作用与数据紧密结合:当副作用函数依赖于多个响应式数据时,watchEffect 可以自动侦测这些数据的变化并重新执行。

无须获取旧值和新值:当你只关心副作用的重新执行,而不需要了解数据变化前后的具体值。


3. 总结对比


4. 适用场景的选择


使用 watch 时:当你明确知道哪些数据需要被监听,并且需要对比数据的旧值和新值,或者需要深度监听复杂的数据结构时,watch 是一个合适的选择。

使用 watchEffect 时:当你希望自动响应当前作用域内的数据变化,并且不关心旧值和新值时,watchEffect 更加方便且简洁。


5.手动停止监听器

通常来说,我们的一个组件被销毁或者卸载后,监听器也会跟着被停止,并不需要我们手动去关闭监听器。但是总是有一些特殊情况,即使组件卸载了,但是监听器依然存在,这个时候其实式需要我们手动关闭它的,否则容易造成内存泄漏。

比如下面这中写法,我们就需要手动停止监听器:

xml
 代码解读
复制代码
<script setup>
import { watchEffect } from 'vue'
// 它会自动停止
watchEffect(() => {})
// ...这个则不会!
setTimeout(() => {
  watchEffect(() => {})
}, 100)
</script>

上段代码中我们采用异步的方式创建了一个监听器,这个时候监听器没有与当前组件绑定,所以即使组件销毁了,监听器依然存在。


关闭方法很简单,代码如下:

scss
 代码解读
复制代码
const unwatch = watchEffect(() => {})
// ...当该侦听器不再需要时
unwatch()

我们需要用一个变量接收监听器函数的返回值,其实就是返回的一个函数,然后我们调用该函数,即可关闭当前监听器。


总结来说,watch 更加灵活和可控,适用于需要显式监听特定响应式数据变化的场景;而 watchEffect 则是更简洁的方案,适用于当副作用依赖于多个响应式数据时,不必显式声明依赖关系的场景。


作者:一阵风一场梦

链接:https://juejin.cn