当前位置: 首页 > article >正文

深入解析 Vue 3 中的 watch 和 watchEffect

深入解析 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.kler.cn/a/399659.html

相关文章:

  • ZSTD 内存泄漏问题
  • 机器学习(基础2)
  • 241113.学习日志——[CSDIY] [ByteDance] 后端训练营 [02]
  • Flutter:Dio下载文件到本地
  • Java 动态代理初步
  • 【MySQL】InnoDB内存结构
  • 基于Lora通讯加STM32空气质量检测WIFI通讯
  • 一个简单的图像分类项目(九)并行训练的学习:多GPU的DP(DataParallel数据并行)
  • 删除缓存之后,浏览器显示登录新设备
  • 【Linux】进程字段、环境变量与进程地址空间
  • 人机混合意识与人类意识不同
  • CVE-2024-2961漏洞的简单学习
  • 蓝队知识浅谈(中)
  • C缺陷与陷阱 — 7 可移植性缺陷
  • 【计算机网络】协议定制
  • uni-app快速入门(五)--判断运行环境及针对不同平台的条件编译
  • ZYNQ程序固化——ZYNQ学习笔记7
  • WebRTC视频 02 - 视频采集类 VideoCaptureModule
  • SQL注入注入方式(大纲)
  • 运算放大器的学习(一)输入阻抗
  • 阅读2020-2023年《国外军用无人机装备技术发展综述》笔记_技术趋势
  • Spring Boot框架:电商系统的技术优势
  • RN开发遇到的坑
  • 力扣 最小路径和
  • Hyper-v中ubuntu与windows文件共享
  • ML 系列: 第 23 节 — 离散概率分布 (多项式分布)