vue3监听属性watch和watchEffect的详解

文章目录

  • 1. 前言
  • 2. 常规用法
  • 3. 监听对象和route变化
  • 4. 使用场景
      • 4.1 即时表单验证
      • 4.2 搜索联想功能
      • 4.3 数据变化联动处理
  • 5. watchEffect详解
    • 5-1 基本概念
    • 5-2 核心用法
      • 基础示例:自动响应依赖变化
      • 处理异步副作用
      • 停止监听与清理副作用
    • 5-3 高级场景应用
      • 监听多个响应式依赖
      • 处理 DOM 副作用
  • 6. watch与watchEffect的对比
    • 选择建议:

1. 前言

在 Vue3 中,watch 是一个独立的函数,用于响应式地监听数据变化并执行回调。与 Vue2 的选项式 API 不同,Vue3 的 watch 主要在 Composition API 中使用,需要从 @vue/composition-api 或 Vue3 核心包中导入。它接收三个参数:监听的数据源、回调函数和可选的配置对象。

Vue3 的 watch 具有以下特点:

  • 更灵活的监听方式,支持监听 ref、reactive 对象和函数返回值
  • 明确的依赖声明,避免依赖收集问题
  • 更强大的配置选项,如深度监听、立即执行等

2. 常规用法

在 Vue3 中使用 watch 需要先导入相关函数,通常在 setup 函数中使用。watch 第一个参数可以是 ref 类型的数据、响应式对象的属性,或者一个返回值的函数。回调函数接收新值和旧值作为参数。

<template><div class="home_box"><h1>{{ total }}</h1><button @click="handleAddTotal">增加</button></div>
</template><script>
import { ref, watch } from 'vue';export default {name: 'Home',setup() {const total = ref(0);// 常规监听 ref 类型数据watch(total, (newValue, oldValue) => {console.log('旧值:', oldValue);console.log('新值:', newValue);});const handleAddTotal = () => {total.value++;};return {total,handleAddTotal};}
}
</script>

3. 监听对象和route变化

Vue3 的 watch 可以监听多种类型的数据,包括响应式对象、嵌套属性和路由变化。对于对象类型的监听,需要注意深度监听的配置;对于路由变化,需要使用特定的监听方式。

<template><div class="home_box"><!-- 页面内容 --></div>
</template><script>
import { ref, reactive, watch } from 'vue';
import { useRoute } from 'vue-router';export default {name: 'Home',setup() {// 基本类型const aaa = ref(0);// 响应式对象const state = reactive({bbb: 0,ccc: {c1: 0,c2: 0},ddd: {d1: 0,d2: {d21: 0}}});// 获取路由实例const route = useRoute();// 监听基本类型watch(aaa, (newValue, oldValue) => {console.log('aaa 旧值:', oldValue);console.log('aaa 新值:', newValue);});// 监听基本类型,初始化立即执行watch(() => state.bbb, (newValue, oldValue) => {console.log('bbb 旧值:', oldValue);console.log('bbb 新值:', newValue);}, { immediate: true });// 监听对象,需要深度监听watch(() => state.ccc, (newValue, oldValue) => {console.log('ccc 旧值:', oldValue);console.log('ccc 新值:', newValue);}, { deep: true });// 监听对象嵌套属性watch(() => state.ddd.d2.d21, (newValue, oldValue) => {console.log('d21 旧值:', oldValue);console.log('d21 新值:', newValue);});// 监听路由变化watch(() => route.path, (newPath, oldPath) => {console.log('路由旧路径:', oldPath);console.log('路由新路径:', newPath);});return {aaa,state};}
}
</script>

4. 使用场景

Vue3 的 watch 在很多场景中都有重要应用,特别是在需要响应数据变化并执行副作用的场景中。以下是几个典型使用场景:

4.1 即时表单验证

<template><div class="home_box"><input type="text" v-model="username"><div v-if="validationError" class="error-message">{{ validationError }}</div></div>
</template><script>
import { ref, watch } from 'vue';export default {name: 'FormValidation',setup() {const username = ref('');const validationError = ref('');// 监听输入框内容变化,即时验证watch(username, (newValue) => {if (newValue.length < 3) {validationError.value = '用户名至少需要3个字符';} else if (newValue.length > 20) {validationError.value = '用户名不能超过20个字符';} else {validationError.value = '';}});return {username,validationError};}
}
</script>

4.2 搜索联想功能

<template><div class="home_box"><input type="text" v-model="searchKeyword"><div v-if="searchResults.length > 0" class="suggestions"><div v-for="result in searchResults" :key="result">{{ result }}</div></div></div>
</template><script>
import { ref, watch } from 'vue';export default {name: 'SearchSuggestions',setup() {const searchKeyword = ref('');const searchResults = ref([]);// 监听搜索关键词变化,延迟发送请求let searchTimeout;watch(searchKeyword, (newValue) => {if (newValue.length < 2) {searchResults.value = [];return;}// 防抖处理,避免频繁请求clearTimeout(searchTimeout);searchTimeout = setTimeout(() => {// 模拟API请求searchResults.value = [`${newValue} 相关结果1`,`${newValue} 相关结果2`,`${newValue} 相关结果3`];}, 500);});return {searchKeyword,searchResults};}
}
</script>

4.3 数据变化联动处理

<template><div class="home_box"><div><label>宽度:</label><input type="number" v-model="width"></div><div><label>高度:</label><input type="number" v-model="height"></div><div>面积:{{ area }}</div></div>
</template><script>
import { ref, watch } from 'vue';export default {name: 'DimensionCalculator',setup() {const width = ref(10);const height = ref(20);const area = ref(0);// 监听宽度和高度变化,计算面积watch([width, height], ([newWidth, newHeight]) => {area.value = newWidth * newHeight;});return {width,height,area};}
}
</script>

5. watchEffect详解

5-1 基本概念

watchEffect 是 Vue3 中 Composition API 提供的响应式副作用监听函数,与 watch 的主动监听不同,它会自动追踪回调函数中使用的响应式依赖,当依赖变化时触发回调。其核心特点包括:

  • 自动依赖收集:无需显式声明监听目标,回调内使用的响应式数据会被自动追踪
  • 初始化立即执行:默认在组件挂载后立即执行一次回调,用于处理初始依赖的副作用
  • 简洁的语法:适用于依赖多个响应式数据的场景,避免重复声明监听源

5-2 核心用法

基础示例:自动响应依赖变化

<template><div class="home_box"><h3>计数器:{{ count }}</h3><h3>翻倍值:{{ doubleCount }}</h3><button @click="count++">+1</button></div>
</template><script>
import { ref, watchEffect } from 'vue';export default {name: 'WatchEffectDemo',setup() {const count = ref(0);const doubleCount = ref(0);// watchEffect 会自动监听 count 的变化watchEffect(() => {console.log('依赖变化触发回调');doubleCount.value = count.value * 2;});// 初始化时立即输出// 控制台打印:依赖变化触发回调return {count,doubleCount};}
}
</script>

处理异步副作用

<template><div class="home_box"><input v-model="searchText" placeholder="搜索..."><div v-if="loading">加载中...</div><div v-else-if="searchResults.length > 0"><ul><li v-for="item in searchResults" :key="item">{{ item }}</li></ul></div><div v-else>无搜索结果</div></div>
</template><script>
import { ref, watchEffect } from 'vue';export default {name: 'SearchEffect',setup() {const searchText = ref('');const searchResults = ref([]);const loading = ref(false);watchEffect(async onInvalidate => {// 当 searchText 变化时,先清除之前的定时器let timeout;onInvalidate(() => clearTimeout(timeout));if (searchText.value.length < 2) {searchResults.value = [];return;}loading.value = true;// 模拟异步搜索timeout = setTimeout(async () => {try {// 模拟API请求const response = await new Promise(resolve => {setTimeout(() => {resolve([`${searchText.value} 结果1`,`${searchText.value} 结果2`,`${searchText.value} 结果3`]);}, 500);});searchResults.value = response;} catch (error) {console.error('搜索失败', error);} finally {loading.value = false;}}, 300);});return {searchText,searchResults,loading};}
}
</script>

停止监听与清理副作用

<template><div class="home_box"><button @click="toggleWatch">{{ isWatching ? '停止监听' : '开始监听' }}</button><div>计数器:{{ count }}</div></div>
</template><script>
import { ref, watchEffect } from 'vue';export default {name: 'WatchEffectControl',setup() {const count = ref(0);const isWatching = ref(true);let watcher = null;// 条件性创建 watchEffectconst toggleWatch = () => {if (isWatching.value) {// 启动监听watcher = watchEffect(() => {console.log('监听中,count:', count.value);});} else {// 停止监听watcher && watcher();}isWatching.value = !isWatching.value;};return {count,isWatching,toggleWatch};}
}
</script>

5-3 高级场景应用

监听多个响应式依赖

<template><div class="home_box"><div><label>宽度:</label><input type="number" v-model="width"></div><div><label>高度:</label><input type="number" v-model="height"></div><div>面积:{{ area }}</div><div>周长:{{ perimeter }}</div></div>
</template><script>
import { ref, watchEffect } from 'vue';export default {name: 'DimensionCalculator',setup() {const width = ref(10);const height = ref(20);const area = ref(0);const perimeter = ref(0);// 同时监听 width 和 height 的变化watchEffect(() => {area.value = width.value * height.value;perimeter.value = 2 * (width.value + height.value);});return {width,height,area,perimeter};}
}
</script>

处理 DOM 副作用

<template><div class="home_box" ref="container"><h3>滚动位置:{{ scrollY }}</h3></div>
</template><script>
import { ref, onMounted, watchEffect } from 'vue';export default {name: 'ScrollEffect',setup() {const container = ref(null);const scrollY = ref(0);onMounted(() => {// 监听容器滚动事件watchEffect(onInvalidate => {if (!container.value) return;const handleScroll = () => {scrollY.value = container.value.scrollTop;};container.value.addEventListener('scroll', handleScroll);// 组件卸载或依赖变化时清理事件onInvalidate(() => {container.value.removeEventListener('scroll', handleScroll);});});});return {container,scrollY};}
}
</script>

6. watch与watchEffect的对比

特性watchwatchEffect
依赖声明方式显式指定监听的数据源(ref、reactive 属性、函数返回值)隐式收集回调函数中使用的响应式依赖
初始化执行默认不执行,需通过 immediate: true 配置初始化时立即执行一次
回调参数接收新值和旧值 (newValue, oldValue)不接收参数,通过闭包访问最新值
适用场景监听特定数据的变化,需要获取新旧值对比处理与多个响应式数据相关的副作用,无需明确依赖
性能优化可精确控制监听目标,避免无效触发依赖收集可能包含不必要的响应式数据,需注意副作用清理
语法复杂度语法相对繁琐,需声明监听源和配置项语法简洁,适合快速实现响应式副作用
异步处理更适合处理需要等待特定数据变化的异步操作适合处理随依赖变化自动更新的异步副作用(如API请求、DOM操作)

选择建议:

  • 使用 watch
    • 需要明确知道监听的数据源
    • 只在特定数据变化时执行回调
    • 需要获取变化前后的新旧值对比
  • 使用 watchEffect
    • 处理与多个响应式数据相关的副作用
    • 初始化时需要立即执行一次副作用
    • 希望以更简洁的方式实现响应式逻辑
// 场景:监听用户登录状态并请求用户数据
setup() {const isLoggedIn = ref(false);const userData = ref(null);// 使用 watch 监听登录状态变化watch(isLoggedIn, (newVal) => {if (newVal) {fetchUserData(); // 只在登录状态变化时请求}});// 使用 watchEffect 自动响应视图更新watchEffect(() => {document.title = `用户状态: ${isLoggedIn.value ? '已登录' : '未登录'}`;});
}

本次分享就到这儿啦,我是鹏多多,如果您看了觉得有帮助,欢迎评论,关注,点赞,转发,我们下次见~

往期文章

  • vue中ref的详解以及react的ref对比
  • css使用aspect-ratio制作4:3和9:16和1:1等等比例布局
  • Web前端页面开发阿拉伯语种适配指南
  • flutter-使用extended_image操作图片的加载和状态处理以及缓存和下载
  • flutter-制作可缩放底部弹出抽屉评论区效果
  • flutter-实现Tabs吸顶的PageView效果
  • Vue2全家桶+Element搭建的PC端在线音乐网站
  • 助你上手Vue3全家桶之Vue3教程
  • 超详细!vue组件通信的10种方式
  • 超详细!Vuex手把手教程
  • 使用nvm管理node.js版本以及更换npm淘宝镜像源
  • vue中利用.env文件存储全局环境变量,以及配置vue启动和打包命令

个人主页

  • CSDN
  • GitHub
  • 掘金

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

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

相关文章

Spring IoC核心实现揭秘

Spring IoC(控制反转)的实现机制是Spring框架的核心,其本质是将对象的创建、依赖管理和生命周期控制权从应用程序代码转移到容器中。以下是其核心实现机制: 🔧 一、核心实现步骤 配置元数据加载 容器启动时读取XML/注解/Java配置类,解析为BeanDefinition对象(包含类名、…

Solidity内部合约创建全解析:解锁Web3开发新姿势

合约创建基础 new 关键字创建合约 在 Solidity 中&#xff0c;new关键字是创建合约实例的最基本方式&#xff0c;它就像是一个 “魔法钥匙”&#xff0c;能够在以太坊区块链上生成一个全新的合约实例。使用new关键字创建合约的过程非常直观&#xff0c;就像我们在其他编程语言…

OCR大模型,破解金融文档处理困境,从文字识别到文字理解

金融机构在日常运营中处理海量文档。这些文档类型多样&#xff0c;格式复杂&#xff0c;是业务运营的基础。如何高效、准确地处理这些文档&#xff0c;直接影响机构的运营效率与风险控制水平。新一代的OCR大模型技术为此提供了有效的解决方案。它提升了文档处理的自动化程度与数…

2025.6.21笔记(2)

1.编写一个程序&#xff0c;输入一个整数&#xff0c;判断它是奇数还是偶数 解题思路&#xff1a; 1.因为要判断输入的数是奇数还是偶数&#xff0c;所以要用到if判断 2.判读奇偶数&#xff1a;如果这个数%20&#xff0c;则它为偶数&#xff0c;如果这个数%2!0&#xff0c;则…

【Ambari3.0.0 部署】Step7—Mariadb初始化-适用于el8

如果有其他系统部署需求可以参考原文 https://doc.janettr.com/install/manual/ MariaDB 10 是 Ambari 及大数据平台的常见数据库方案。本文适配 Rocky Linux 8.10&#xff0c;涵盖 MariaDB 10.11 推荐安装、YUM 源配置、参数优化、初始化和安全设置&#xff0c;帮助你一步到位…

SpringBoot电脑商城项目--删除收获地址+热销排行

删除收获地址 1 删除收获地址-持久层 1.1 规划sql语句 在删除操作之前判断该数据是否存在&#xff0c;判断该条地址的归属是否是当前的用户执行删除收货地址的操作 delete from t_address where aid? 如果用户删除的时默认地址&#xff0c;将剩下地址的某一条作为默认收货地…

MIMIC-III 数据集文件简介

文件简介&#xff1a; 共26个文件 admissions.csv 患者入院信息&#xff08;入院时间、出院时间、入院类型、科室等&#xff09;。 callout.csv ICU 外科室请求 ICU 会诊的呼叫记录。 caregivers.csv 护理患者的医护人员信息&#xff08;身份、角色等&#xff09;。…

UL/CE双认证!光宝MOC3052-A双向可控硅输出光耦 智能家居/工业控制必备!

光宝MOC3052-A双向可控硅输出光耦详解 1. 产品定位 MOC3052-A 是光宝科技&#xff08;Lite-On&#xff09;推出的 双向可控硅驱动光耦&#xff0c;属于光电隔离型半导体器件&#xff0c;主要用于交流负载的隔离控制&#xff0c;实现低压控制电路&#xff08;如MCU&#xff09;…

让没有小窗播放的视频网站的视频小窗播放

让没有小窗播放的视频网站的视频小窗播放 // 视频小窗播放控制台脚本 // 将此代码复制到浏览器控制台运行 // 运行后&#xff0c;页面中的视频将添加小窗播放功能(function() {// 获取页面中的所有video元素const videos document.querySelectorAll(video);if (videos.length…

Linux内核在启动过程中挂载根文件系统rootfs的过程

一、挂载根文件系统rootfs的过程&#xff1a; 1. ‌初始虚拟根文件系统的挂载‌ 内核启动时首先会创建并挂载一个‌临时虚拟根文件系统&#xff08;如initramfs或rootfs&#xff09;‌‌15。该阶段主要作用&#xff1a; 提供基础的设备节点和目录结构&#xff0c;确保内核能访…

【LeetCode】力扣题——轮转数组、消失的数字、数组串联

&#x1f525;个人主页&#xff1a;艾莉丝努力练剑 ❄专栏传送门&#xff1a;《C语言》、《数据结构与算法》、C语言刷题12天IO强训 &#x1f349;学习方向&#xff1a;C/C方向 ⭐️人生格言&#xff1a;为天地立心&#xff0c;为生民立命&#xff0c;为往圣继绝学&#xff0c;…

Java Stream详解

Java Stream详解 Stream 是 Java 8 引入的流式数据处理工具&#xff0c;可以像流水线一样对集合数据进行高效操作&#xff08;过滤、转换、统计等&#xff09;。核心特点&#xff1a; 链式操作&#xff1a;支持多个操作串联不修改原始数据&#xff1a;生成新结果支持并行处理…

Java回归循环理解

一、Java循环的四种 1. 传统for循环 - 精确控制的首选 // 遍历数组 int[] numbers {1, 2, 3, 4, 5}; for (int i 0; i < numbers.length; i) {System.out.println(numbers[i]); }// 嵌套示例&#xff1a;矩阵遍历 int[][] matrix {{1, 2}, {3, 4}}; for (int row 0; r…

飞腾D2000金融工控主板,点亮经济高质量发展

近年来&#xff0c;国家不断推出金融行业的政策和法规&#xff0c;推动金融业高质量发展。在国家大力推进金融行业改革和创新的大环境下&#xff0c;金融工控主板市场也迎来了新的发展机遇。随着国产CPU技术的不断突破&#xff0c;以及我国对金融安全重视程度的提高&#xff0c…

SimpleITK——创建nrrd体素模型

在介绍如何生成nrrd前&#xff0c;了解一下为什么医学影像上一般使用nrrd的体素模型&#xff1f; 为什么医学影像上一般使用nrrd的体素模型&#xff1f; 在医学影像领域&#xff0c;‌NRRD&#xff08;Nearly Raw Raster Data&#xff09;格式‌被广泛用于存储体素模型&#x…

Docker容器部署KES

一、安装部署 1&#xff0c;导入镜像 #导入镜像&#xff08;root用户&#xff09; [rootnode docker ]# mv kdb_x86_64_V008R006C009B0014.tar kingbase.tar [rootnode docker]# docker load -i kingbase.tar#查看镜像&#xff08;root用户&#xff09; [rootnode docker]# d…

C++基础练习 sort函数,用于排序函数

题目&#xff1a; https://acm.hdu.edu.cn/showproblem.php?pid2039 解答&#xff1a; #include <iostream> #include <cmath> #include <algorithm> using namespace std;double a[3]; int main(){int n;cin>>n;while(n--){cin>>a[0]>>…

棱镜观察|EMB“重构”卡钳,车企降本压力与Brembo困局

传统制动卡钳市场&#xff0c;正在迎来变革时刻。 一直以来&#xff0c;采埃孚、大陆集团、日立安斯泰莫等外资供应商占据中国乘用车卡钳前装市场&#xff08;包括前制动卡钳和后集成EPB卡钳&#xff09;的半壁江山。同时&#xff0c;伯特利、亚太股份、万向、弗迪等中国供应商…

《颠覆传统:CSS遮罩的图像创意设计指南》

想象有一块神奇的模板&#xff0c;上面有各种形状的镂空区域&#xff0c;当我们将这块模板覆盖在图像上时&#xff0c;只有透过镂空区域才能看到图像的部分&#xff0c;而模板遮挡的地方则被隐藏起来&#xff0c;这便是CSS遮罩的核心概念。遮罩&#xff0c;简单来说&#xff0c…

5.基于神经网络的时间序列预测

近年来&#xff0c;已经开发了一些深度学习方法并将其应用于单变量时间预测场景&#xff0c;其中时间序列由在等时间增量上按顺序记录的单个观测数据组成。 5.1 将深度学习用于时间序列预测的原因 机器学习的目标是提取特征来训练模型。模型将输入数据&#xff08;例如图片&am…