深入理解 Vue 3 中 watch 与 watchEffect 的区别

在 Vue 3 的响应式系统里,watchwatchEffect 是监听响应式数据变化的重要函数,它们在不同场景下发挥着关键作用。本文将详细介绍这两个函数,并结合代码示例说明它们的区别。

简单状态绑定与计算属性

ref 与 reactive 实现简单状态绑定

在 Vue 3 中,refreactive 用于创建响应式数据。ref 常用于基本数据类型的响应式包装,而 reactive 则用于对象和数组的响应式处理。

xml 复制代码
<template>
  <div>
    <p>{{ count }}</p>
    <p>{{ user.name }}</p>
  </div>
</template>

<script setup>
import { ref, reactive } from 'vue';

// 使用 ref 创建响应式数据
const count = ref(0);

// 使用 reactive 创建响应式对象
const user = reactive({ name: 'John' });
</script>

computed 实现响应式数据计算

computed 用于创建响应式计算属性,它会自动处理依赖,当依赖的数据发生变化时,计算属性会自动更新。以购物车总价计算为例:

xml 复制代码
<template>
  <div>
    <p>商品单价:{{ price }}</p>
    <p>商品数量:{{ quantity }}</p>
    <p>总价:{{ total }}</p>
  </div>
</template>

<script setup>
import { ref, computed } from 'vue';

// 商品单价
const price = ref(10);
// 商品数量
const quantity = ref(2);

// 计算总价
const total = computed(() => price.value * quantity.value);
</script>

watch:监听响应式数据变化执行复杂逻辑

手动指定依赖执行复杂业务

watch 函数用于监听特定的响应式数据变化,并在数据变化时执行复杂的逻辑,如异步请求、检查库存等。以下是一个简单的示例,监听 count 的变化,并在变化时发起异步请求:

vue

xml 复制代码
<template>
  <div>
    <button @click="count++">增加计数</button>
    <p>计数:{{ count }}</p>
  </div>
</template>

<script setup>
import { ref, watch } from 'vue';

// 创建响应式数据
const count = ref(0);

// 监听 count 的变化
watch(count, async (newValue, oldValue) => {
  // 模拟异步请求
  const response = await fetch(`https://api.example.com/data?count=${newValue}`);
  const data = await response.json();
  console.log('异步请求结果:', data);
});
</script>

立即执行监听逻辑

默认情况下,watch 是惰性的,即只有在监听的数据发生变化时才会执行回调函数。如果需要在组件初始化时立即执行回调函数,可以设置 immediate: true

xml 复制代码
<template>
  <div>
    <p>计数:{{ count }}</p>
  </div>
</template>

<script setup>
import { ref, watch } from 'vue';

// 创建响应式数据
const count = ref(0);

// 立即执行监听逻辑
watch(count, (newValue, oldValue) => {
  console.log(`计数从 ${oldValue} 变为 ${newValue}`);
}, { immediate: true });
</script>

watchEffect:立即执行并自动处理依赖

自动收集依赖并执行副作用

watchEffect 会立即执行传入的回调函数,并自动追踪回调函数中使用的所有响应式依赖。当这些依赖发生变化时,回调函数会再次执行。以下是一个示例:

xml 复制代码
<template>
  <div>
    <button @click="count++">增加计数</button>
    <p>计数:{{ count }}</p>
  </div>
</template>

<script setup>
import { ref, watchEffect } from 'vue';

// 创建响应式数据
const count = ref(0);

// 立即执行并自动处理依赖
watchEffect(() => {
  console.log(`当前计数为 ${count.value}`);
});
</script>

总结

  • 手动 vs 自动watch 需要手动指定要监听的依赖,而 watchEffect 会自动收集依赖。

  • 立即执行watchEffect 会立即执行一次回调函数,而 watch 默认是惰性的,需要设置 immediate: true 才能立即执行。

  • 使用场景watch 适用于需要明确知道数据变化前后的值,并执行复杂逻辑的场景;watchEffect 适用于只关心副作用的执行,而不关心具体是哪个依赖导致了副作用执行的场景。

通过合理使用 watchwatchEffect,可以更好地管理 Vue 3 应用中的响应式数据变化,提高代码的可维护性和性能。

相关推荐
军军君0129 分钟前
Three.js基础功能学习十三:太阳系实例上
前端·javascript·vue.js·学习·3d·前端框架·three
xiaoqi9221 小时前
React Native鸿蒙跨平台如何实现分类页面组件通过searchQuery状态变量管理搜索输入,实现了分类的实时过滤功能
javascript·react native·react.js·ecmascript·harmonyos
qq_177767372 小时前
React Native鸿蒙跨平台实现应用介绍页,实现了应用信息卡片展示、特色功能网格布局、权限/联系信息陈列、评分展示、模态框详情交互等通用场景
javascript·react native·react.js·ecmascript·交互·harmonyos
2603_949462102 小时前
Flutter for OpenHarmony社团管理App实战:预算管理实现
android·javascript·flutter
wuhen_n2 小时前
JavaScript内存管理与执行上下文
前端·javascript
Hi_kenyon2 小时前
理解vue中的ref
前端·javascript·vue.js
jin1233223 小时前
基于React Native鸿蒙跨平台地址管理是许多电商、外卖、物流等应用的重要功能模块,实现了地址的添加、编辑、删除和设置默认等功能
javascript·react native·react.js·ecmascript·harmonyos
2501_920931704 小时前
React Native鸿蒙跨平台医疗健康类的血压记录,包括收缩压、舒张压、心率、日期、时间、备注和状态
javascript·react native·react.js·ecmascript·harmonyos
橙露4 小时前
React Hooks 深度解析:从基础使用到自定义 Hooks 的封装技巧
javascript·react.js·ecmascript
2501_920931705 小时前
React Native鸿蒙跨平台使用useState管理健康记录和过滤状态,支持多种健康数据类型(血压、体重等)并实现按类型过滤功能
javascript·react native·react.js·ecmascript·harmonyos