Vue3的watchEffect

举报
周杰伦本人 发表于 2025/01/22 16:32:13 2025/01/22
【摘要】 Vue3的watchEffect在 Vue 3 中,watchEffect 是一个强大的 API,用于自动追踪响应式数据的变化并执行副作用(side effects)。它与 watch 的主要区别在于,watchEffect 不需要显式指定要监视的响应式数据,而是会自动追踪回调函数中访问的响应式数据。问题背景:水质监测系统假设你正在开发一个水质监测系统,需要实时监控水温(temp)和水位(h...

Vue3的watchEffect

在 Vue 3 中,watchEffect 是一个强大的 API,用于自动追踪响应式数据的变化并执行副作用(side effects)。它与 watch 的主要区别在于,watchEffect 不需要显式指定要监视的响应式数据,而是会自动追踪回调函数中访问的响应式数据。

问题背景:水质监测系统

假设你正在开发一个水质监测系统,需要实时监控水温(temp)和水位(height)。具体需求如下:

  1. 水温监控:当水温达到或超过 60°C 时,需要向服务器发送警告请求。

  2. 水位监控:当水位达到或超过 80cm 时,也需要向服务器发送警告请求。

问题描述

  • 水温水位 是两个独立的响应式数据。

  • 需要实时监控这两个数据的变化,并在满足条件时执行特定操作(如发送请求)。

  • 需要一个简洁且高效的方式来实现这一功能。


实现思路

  1. 使用 watch
  • watch 需要显式指定要监视的数据。

  • 需要手动处理多个数据的依赖关系。

  • 需要手动处理回调函数中的逻辑。

  1. 使用 watchEffect
  • watchEffect 自动追踪回调函数中访问的响应式数据。

  • 不需要显式指定依赖项,代码更简洁。

  • 默认立即执行回调函数,并在依赖数据变化时重新执行。


代码实现

使用 watch 实现

HTML复制

<template>
  <div>
    <h1>水质监测系统</h1>
    <p>当前水温:{{ temp }}°C</p>
    <p>当前水位:{{ height }}cm</p>
    <button @click="increaseTemp">水温 + 10°C</button>
    <button @click="increaseHeight">水位 + 10cm</button>
  </div>
</template>

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

const temp = ref(10); // 初始水温
const height = ref(0); // 初始水位

const increaseTemp = () => {
  temp.value += 10;
};

const increaseHeight = () => {
  height.value += 10;
};

watch([temp, height], ([newTemp, newHeight], [oldTemp, oldHeight]) => {
  console.log(`水温从 ${oldTemp}°C 变为 ${newTemp}°C`);
  console.log(`水位从 ${oldHeight}cm 变为 ${newHeight}cm`);

  if (newTemp >= 60 || newHeight >= 80) {
    console.log('发送警告请求到服务器');
  }
});
</script>

使用 watchEffect 实现

HTML复制

<template>
  <div>
    <h1>水质监测系统</h1>
    <p>当前水温:{{ temp }}°C</p>
    <p>当前水位:{{ height }}cm</p>
    <button @click="increaseTemp">水温 + 10°C</button>
    <button @click="increaseHeight">水位 + 10cm</button>
  </div>
</template>

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

const temp = ref(10); // 初始水温
const height = ref(0); // 初始水位

const increaseTemp = () => {
  temp.value += 10;
};

const increaseHeight = () => {
  height.value += 10;
};

watchEffect(() => {
  if (temp.value >= 60 || height.value >= 80) {
    console.log('发送警告请求到服务器');
  }
});
</script>

对比分析

有没有发现watchEffectwatch的代码要简单一些呢?而且watchEffect会自动分析数据的变化从而做出相应的响应,而watch需要指定具体的变量

  1. 代码简洁性
  • watch:需要显式指定依赖项 [temp, height],并处理回调函数中的逻辑。

  • watchEffect:自动追踪回调函数中访问的响应式数据,代码更简洁。

  1. 立即执行
  • watch:默认不立即执行,需要显式指定 { immediate: true }

  • watchEffect:默认立即执行回调函数。

  1. 灵活性
  • watch:适合需要显式控制依赖项的场景。

  • watchEffect:适合简单的响应式副作用处理,自动追踪依赖项。


通过上述问题和代码实现,你可以看到 watchEffect 在处理简单逻辑时的简洁性和高效性。它自动追踪依赖项,无需显式指定,非常适合动态响应数据变化的场景。在实际开发中,你可以根据具体需求选择使用 watchwatchEffect,以实现更高效的数据监听和副作用管理。

watchEffect 的特点

那我们现在知道了,watchEffect 有以下特点

  1. 自动追踪依赖
  • watchEffect 会自动追踪回调函数中访问的响应式数据。你不需要显式指定依赖项,这使得代码更简洁、更易读。

  • 例如,如果回调中访问了 refreactive 的属性,这些属性会被自动添加为依赖。

  1. 立即执行
  • watchEffect 在组件挂载时会立即执行一次回调函数,而 watch 默认不会立即执行,除非显式指定 { immediate: true }
  1. 响应式副作用
  • 当依赖的响应式数据变化时,watchEffect 会重新执行回调函数,确保始终获取最新的状态。
  1. 灵活性
  • watchEffect 可以与 refreactive 等响应式 API 结合使用,灵活处理不同的数据类型和结构。

watchEffect 的基本用法

JavaScript复制

import { ref, watchEffect } from 'vue';

const count = ref(0);
watchEffect(() => {
  console.log(`count is now ${count.value}`);
});

在这个例子中,watchEffect 会立即执行,并在 count 变化时输出新的值。

watchwatchEffect 的对比

|特性|watch|watchEffect| |-|-|-| |依赖声明|需要显式指定要监听的响应式数据|自动追踪内部访问的响应式数据| |回调参数|提供 newValoldVal|无法直接访问变化前后的值| |立即执行|默认不立即执行(可通过 { immediate: true } 控制)|默认立即执行| |适用场景|适合特定数据变化时执行操作|适合简单逻辑的响应式副作用处理|

watchEffect 的原理

那它的原理是什么呢,为什么能够做到自动依赖追踪呢?

Vue 3 使用 Proxy 来实现响应式系统,这是 watchEffect 自动依赖追踪的基础。Proxy 是一个强大的 JavaScript API,可以拦截对象的操作(如读取、设置属性等),并触发相应的副作用。

(一)响应式对象的创建

JavaScript复制

import { reactive } from 'vue';

const state = reactive({
  temp: 10,
  height: 0
});
  • reactive 函数会将对象包装成一个响应式对象。

  • Proxy 会拦截对对象的读取和修改操作。

(二)响应式引用的创建

JavaScript复制

import { ref } from 'vue';

const temp = ref(10);
const height = ref(0);
  • ref 函数会创建一个响应式引用对象,其内部使用 Proxy 实现。

二、依赖收集

watchEffect 的回调函数执行时,Vue 会自动追踪回调中访问的所有响应式数据。这些数据被添加为依赖项。

(一)自动追踪依赖

JavaScript复制

import { watchEffect } from 'vue';

watchEffect(() => {
  console.log(`当前水温:${temp.value}°C`);
  console.log(`当前水位:${height.value}cm`);
});
  • 在回调函数中访问 temp.valueheight.value 时,Vue 会自动将 tempheight 添加为依赖项。

  • Proxy 拦截了对 tempheight 的读取操作,并记录了这些依赖。

(二)依赖更新

  • tempheight 的值发生变化时,Proxy 会触发副作用。

  • watchEffect 会重新执行回调函数,确保回调函数始终能够获取最新的数据状态。

三、重新执行回调

watchEffect 的回调函数会在以下情况下重新执行:

  1. 依赖项变化:当依赖的响应式数据发生变化时,Proxy 会触发副作用,watchEffect 会重新执行回调函数。

  2. 组件挂载时watchEffect 的回调函数会在组件挂载时立即执行一次。

(一)立即执行

JavaScript复制

watchEffect(() => {
  console.log(`当前水温:${temp.value}°C`);
  console.log(`当前水位:${height.value}cm`);
});
  • 回调函数会在组件挂载时立即执行一次,收集依赖项。

(二)依赖项变化时重新执行

JavaScript复制

watchEffect(() => {
  if (temp.value >= 60 || height.value >= 80) {
    console.log('发送警告请求到服务器');
  }
});
  • tempheight 的值发生变化时,watchEffect 会重新执行回调函数。

让我们来总结一下:

(一)Proxy 拦截

  • Proxy 拦截对象的读取和修改操作,记录依赖项。

  • 当依赖项变化时,Proxy 触发副作用。

(二)自动依赖收集

  • watchEffect 的回调函数执行时,Vue 自动追踪回调中访问的响应式数据。

  • 这些数据被自动添加为依赖项,无需显式指定。

(三)重新执行

  • 当依赖项变化时,watchEffect 会重新执行回调函数。

  • 回调函数在组件挂载时立即执行一次。

通过上述机制,watchEffect 实现了自动依赖追踪和重新执行回调的功能,使得开发者可以更简洁地处理响应式副作用。

总结

watchEffect 是 Vue 3 中处理响应式数据变化和副作用的工具之一。它自动追踪依赖,无需显式指定依赖项,适合简单逻辑的响应式副作用处理。在实际开发中,还要根据具体需求选择使用 watchwatchEffect,以实现更高效的数据监听和副作用管理。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。