深入解析 Vue 3 中的 watch 和 watchEffect

news2024/11/19 3:04:03

深入解析 Vue 3 中的 watchwatchEffect

在 Vue 3 中,watchwatchEffect 是非常重要的工具,分别用于监听响应式数据的变化,并在变化时执行特定逻辑。它们在数据变化处理、实时副作用、调试等场景中尤为有用。

本文将从以下几个方面详细解析它们的用法和差异,并通过语法糖编写示例代码:

  1. watch 的基础用法
  2. watchEffect 的基础用法
  3. 二者的差异与适用场景
  4. 高级用法与性能优化
  5. 常见问题与注意事项

一、watch 的基础用法

watch 是 Vue 3 提供的监听器,用于监视特定的响应式数据变化,并在数据发生变化时执行回调。

1. 监听单个响应式数据

示例代码:
<script setup>
import { ref, watch } from 'vue'

// 定义响应式数据
const count = ref(0)

// 监听 count 的变化
watch(count, (newVal, oldVal) => {
  console.log(`count 从 ${oldVal} 变为 ${newVal}`)
})
</script>

<template>
  <div>
    <p>计数器:{{ count }}</p>
    <button @click="count++">增加</button>
  </div>
</template>

运行说明

  • count 发生变化时,watch 会触发回调,并传入两个参数:
    • newVal:变化后的新值。
    • oldVal:变化前的旧值。

2. 监听多个数据

可以使用 watch 同时监听多个响应式数据,传入一个数组。

示例代码:
<script setup>
import { ref, watch } from 'vue'

const firstName = ref('张')
const lastName = ref('三')

// 同时监听 firstName 和 lastName 的变化
watch([firstName, lastName], ([newFirst, newLast], [oldFirst, oldLast]) => {
  console.log(`姓名从 ${oldFirst} ${oldLast} 变为 ${newFirst} ${newLast}`)
})
</script>

<template>
  <div>
    <input v-model="firstName" placeholder="姓" />
    <input v-model="lastName" placeholder="名" />
  </div>
</template>

3. 深度监听(deep 选项)

默认情况下,watch 不会深度监听对象内部的变化。若要深度监听,可以设置 { deep: true }

示例代码:
<script setup>
import { ref, watch } from 'vue'

const user = ref({
  name: '张三',
  age: 25
})

// 深度监听对象内部的变化
watch(
  user,
  (newVal, oldVal) => {
    console.log('用户信息发生变化:', newVal, oldVal)
  },
  { deep: true }
)
</script>

<template>
  <div>
    <input v-model="user.name" placeholder="名字" />
    <input v-model.number="user.age" placeholder="年龄" />
  </div>
</template>

注意

  • deep 会递归监听对象内部的每一层属性,可能带来性能开销。

4. 立即执行(immediate 选项)

watch 默认不会在初始化时立即执行。如果需要立即触发,可以设置 { immediate: true }

示例代码:
<script setup>
import { ref, watch } from 'vue'

const message = ref('Hello Vue 3')

// 监听时立即执行一次回调
watch(
  message,
  (newVal, oldVal) => {
    console.log('立即执行:', newVal)
  },
  { immediate: true }
)
</script>

二、watchEffect 的基础用法

watchEffect 是 Vue 3 新增的一个更灵活的工具,可以自动追踪其内部使用的响应式数据,并在这些数据变化时重新执行回调。

1. 基础用法

示例代码:
<script setup>
import { ref, watchEffect } from 'vue'

const count = ref(0)
const double = ref(0)

// 自动追踪响应式数据
watchEffect(() => {
  double.value = count.value * 2
  console.log(`count: ${count.value}, double: ${double.value}`)
})
</script>

<template>
  <div>
    <p>计数器:{{ count }}</p>
    <p>双倍值:{{ double }}</p>
    <button @click="count++">增加</button>
  </div>
</template>

2. 自动追踪依赖

watch 不同,watchEffect 不需要明确指定要监听的目标,而是会根据回调函数中访问的响应式数据自动追踪依赖。

代码分析

  • 在回调中访问了 count.value,因此 count 被自动添加为依赖。
  • 每当 count 发生变化时,watchEffect 会重新执行。

3. 停止监听

通过 watchEffect 返回的函数可以手动停止监听。

示例代码:
<script setup>
import { ref, watchEffect } from 'vue'

const count = ref(0)

// watchEffect 会返回一个函数,这个返回的函数是用来停止监听的。
// 当你调用这个返回的函数时,Vue 会清理与当前 watchEffect 回调关联的依赖
// 并停止触发回调
const stop = watchEffect(() => {
  console.log(`count: ${count.value}`)
})

// 停止监听
const stopWatching = () => {
  stop()
  console.log('已停止监听')
}
</script>

<template>
  <div>
    <p>计数器:{{ count }}</p>
    <button @click="count++">增加</button>
    <button @click="stopWatching">停止监听</button>
  </div>
</template>

三、watchwatchEffect 的对比

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

四、高级用法与性能优化

1. 组合 watchcomputed

在复杂场景下,可以将 computedwatch 配合使用,分离逻辑和副作用。

示例代码:
<script setup>
import { ref, computed, watch } from 'vue'

const basePrice = ref(100)
const discount = ref(10)

// 使用 computed 计算最终价格
const finalPrice = computed(() => basePrice.value - discount.value)

// 使用 watch 触发副作用
watch(finalPrice, (newPrice) => {
  console.log(`最终价格更新为: ${newPrice}`)
})
</script>

<template>
  <div>
    <p>最终价格:{{ finalPrice }}</p>
    <input v-model.number="basePrice" type="number" placeholder="原价" />
    <input v-model.number="discount" type="number" placeholder="折扣" />
  </div>
</template>

2. 性能优化:避免深度监听和频繁回调

  • 避免在 watch 中使用 deep 选项监听大型对象。
  • 对于复杂计算,优先使用 computed

五、常见问题与注意事项

  1. watchEffect 不适合复杂逻辑

    • 因为它无法提供变化前后的值,不适合需要对比 newValoldVal 的场景。
  2. 防止无限循环

    • 如果在 watchwatchEffect 中直接修改被监听的响应式数据,可能导致无限循环。可以通过条件判断避免这种情况。

六、总结

  • watch:适合明确监听指定的响应式数据,常用于特定逻辑处理和副作用操作。
  • watchEffect:适合自动追踪依赖的响应式数据,快速实现响应式副作用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2243139.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【AlphaFold3】开源本地的安装及使用

文章目录 安装安装DockerInstalling Docker on Host启用Rootless Docker 安装 GPU 支持安装 NVIDIA 驱动程序安装 NVIDIA 对 Docker 的支持 获取 AlphaFold 3 源代码获取基因数据库获取模型参数构建将运行 AlphaFold 3 的 Docker 容器 参考 AlphaFold3: https://github.com/goo…

[JAVA]MyBatis框架—获取SqlSession对象

SqlSessionFactory作为MyBatis框架的核心接口有三大特性 SqlSessionFactory是MyBatis的核心对象 用于初始化MyBatis&#xff0c;创建SqlSession对象 保证SqlSessionFactory在应用中全局唯一 1.SqlSessionFactory是MyBatis的核心对象 假设我们要查询数据库的用户信息&#x…

ArkTS学习笔记:ArkTS起步

ArkTS是HarmonyOS的主力应用开发语言&#xff0c;基于TypeScript扩展&#xff0c;强化了静态检查和分析&#xff0c;旨在提升程序稳定性和性能。它采用静态类型&#xff0c;禁止运行时改变对象布局&#xff0c;并对UI开发框架能力进行扩展&#xff0c;支持声明式UI描述和自定义…

JAVA 之 JDBC

JDBC概述 基本介绍 1.JDBC为访问不同的数据库提供了统一的接口&#xff0c;为使用者屏蔽了细节问题。 2.Java程序员使用JDBC,可以连接任何提供了JDBC驱动程序的数据库系统&#xff0c;从而完成对数据库的各种操作。 3.JDBC的基本原理[ 重要 ] 4.模拟JDBC com.lmbc.myjdbc…

用 Python 从零开始创建神经网络(五):损失函数(Loss Functions)计算网络误差

用损失函数&#xff08;Loss Functions&#xff09;计算网络误差 引言1. 分类交叉熵损失&#xff08;Categorical Cross-Entropy Loss&#xff09;2. 分类交叉熵损失类&#xff08;The Categorical Cross-Entropy Loss Class&#xff09;展示到目前为止的所有代码3. 准确率计算…

Redis做分布式锁

&#xff08;一&#xff09;为什么要有分布式锁以及本质 在一个分布式的系统中&#xff0c;会涉及到多个客户端访问同一个公共资源的问题&#xff0c;这时候我们就需要通过锁来做互斥控制&#xff0c;来避免类似于线程安全的问题 因为我们学过的sychronized只能对线程加锁&…

阿里云引领智算集群网络架构的新一轮变革

阿里云引领智算集群网络架构的新一轮变革 云布道师 11 月 8 日~ 10 日在江苏张家港召开的 CCF ChinaNet&#xff08;即中国网络大会&#xff09;上&#xff0c;众多院士、教授和业界技术领袖齐聚一堂&#xff0c;畅谈网络未来的发展方向&#xff0c;聚焦智算集群网络的创新变…

预处理(1)(手绘)

大家好&#xff0c;今天给大家分享一下编译器预处理阶段&#xff0c;那么我们来看看。 上面是一些预处理阶段的知识&#xff0c;那么明天给大家讲讲宏吧。 今天分享就到这里&#xff0c;谢谢大家&#xff01;&#xff01;

ZYNQ程序固化——ZYNQ学习笔记7

一、ZYNQ启动过程 二、 SD卡启动实操 1、对ZYNQ进行配置添加Flash 2、添加SD卡 3、重新生成硬件信息 4、创建vitis工程文件 5、勾选板级支持包 6、对系统工程进行整体编译&#xff0c;生成两个Debug文件&#xff0c;如图所示。 7、插入SD卡&#xff0c;格式化为 8、考入BOOT.…

FPGA实现PCIE采集电脑端视频转SFP光口万兆UDP输出,基于XDMA+GTX架构,提供2套工程源码和技术支持

目录 1、前言工程概述免责声明 2、相关方案推荐我已有的PCIE方案10G Ethernet Subsystem实现万兆以太网物理层方案 3、PCIE基础知识扫描4、工程详细设计方案工程设计原理框图电脑端视频PCIE视频采集QT上位机XDMA配置及使用XDMA中断模块FDMA图像缓存UDP视频组包发送UDP协议栈MAC…

Mongo数据库集群搭建

目录 1、Mongo集群优势 1.1 高可用性 1.2 水平扩展性 1.3 高性能 1.4 灵活的架构设计 1.5 数据安全 1.6 管理与监控 2、下载指定操作系统版本包 3、部署和验证工作 3.1 准备配置文件及依赖 3.2 启动第一个节点 3.3 部署更多的节点 3.4 初始化副本集 3.5 设置管理…

创建vue3项目步骤

脚手架创建项目&#xff1a; pnpm create vue Cd 项目名称安装依赖&#xff1a;Pnpm iPnpm Lint&#xff1a;修复所有文件风格 &#xff0c;不然eslint语法警告报错要双引号Pnpm dev启动项目 拦截错误代码提交到git仓库&#xff1a;提交前做代码检查 pnpm dlx husky-in…

C语言项⽬实践-贪吃蛇

目录 1.项目要点 2.窗口设置 2.1mode命令 2.2title命令 2.3system函数 2.Win32 API 2.1 COORD 2.2 GetStdHandle 2.3 CONSOLE_CURSOR_INFO 2.4 GetConsoleCursorInfo 2.5 SetConsoleCursorInfo 2.5 SetConsoleCursorPosition 2.7 GetAsyncKeyState 3.贪吃蛇游戏设…

nfs服务器--RHCE

一&#xff0c;简介 NFS&#xff08;Network File System&#xff0c;网络文件系统&#xff09;是FreeBSD支持的文件系统中的一种&#xff0c;它允许网络中的计 算机&#xff08;不同的计算机、不同的操作系统&#xff09;之间通过TCP/IP网络共享资源&#xff0c;主要在unix系…

自动化运维(k8s):一键获取指定命名空间镜像包脚本

前言&#xff1a;脚本写成并非一蹴而就&#xff0c;需要不断的调式和修改&#xff0c;这里也是改到了7版本才在 生产环境 中验证成功。 该命令 和 脚本适用于以下场景&#xff1a;在某些项目中&#xff0c;由于特定的安全或政策要求&#xff0c;不允许连接到你的镜像仓库。然而…

HuggingFace:基于YOLOv8的人脸检测模型

个人操作经验总结 1、YOLO的环境配置 github 不论base环境版本如何&#xff0c;建议在conda的虚拟环境中安装 1.1、创建虚拟环境 conda create -n yolov8-face python3.9conda create &#xff1a;创建conda虚拟环境&#xff0c; -n &#xff1a;给虚拟环境命名的…

Unet++改进28:添加PPA(2024最新改进方法)|多分支特征提取策略,捕获不同尺度和层次的特征信息。

本文内容:添加PPA 目录 论文简介 1.步骤一 2.步骤二 3.步骤三 4.步骤四 论文简介 红外小目标检测是一项重要的计算机视觉任务,涉及对红外图像中通常只有几个像素的微小目标进行识别和定位。然而,由于红外图像中物体的体积小,背景一般比较复杂,这给红外图像的识别带来…

CTF攻防世界小白刷题自学笔记13

1.fileinclude,难度&#xff1a;1,方向&#xff1a;Web 题目来源:宜兴网信办 题目描述:无 给一下题目链接&#xff1a;攻防世界Web方向新手模式第16题。 打开一看给了很多提示&#xff0c;什么language在index.php的第九行&#xff0c;flag在flag.php中&#xff0c;但事情显…

同三维T610UDP-4K60 4K60 DP或HDMI或手机信号采集卡

1路DP/HDMI/TYPE-C&#xff08;手机/平板等&#xff09;视频信号输入1路MIC1路LINE OUT,带1路HDMI环出&#xff0c;USB免驱&#xff0c;分辨率4K60&#xff0c;可采集3路信号中其中1路&#xff0c;按钮切换&#xff0c;可采集带TYPE-C接口的各品牌手机/平板/笔记本电脑等 同三维…

小程序如何完成订阅

小程序如何完成订阅 参考相关文档实践问题处理授权弹窗不再触发引导用户重新授权 参考相关文档 微信小程序实现订阅消息推送的实现步骤 发送订阅消息 小程序订阅消息&#xff08;用户通过弹窗订阅&#xff09;开发指南 实践 我们需要先选这一个模板&#xff0c;具体流程参考…