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

Vue学习笔记集--watch

watch

在 Vue 3 的 Composition API 中,watchwatchEffect 是用于响应式侦听数据变化的核心 API。它们都能追踪依赖并执行副作用,但在使用方式和场景上有显著差异。以下是详细解析:


watchwatchEffect 对比

特性watchwatchEffect
依赖收集方式显式指定侦听的数据源自动收集回调函数内的响应式依赖
立即执行默认不立即执行(可通过 immediate: true 开启)总是立即执行
旧值访问可获取旧值(oldValue无法获取旧值
适用场景需要精确控制侦听目标依赖多个数据或需要自动追踪依赖的场景

watch 的深度解析

1. 基本语法
import { watch, ref } from 'vue';

const count = ref(0);

// 监听单个 ref
watch(count, (newVal, oldVal) => {
  console.log(`count变化:${oldVal}${newVal}`);
});

// 监听多个源(数组形式)
watch([count, otherRef], ([newCount, newOther], [oldCount, oldOther]) => {
  // 处理多个变化
});
2. 监听不同类型的数据源
  • Ref 类型

    const num = ref(0);
    watch(num, (newVal) => { /* ... */ });
    
  • Reactive 对象属性

    const state = reactive({ user: { name: 'Alice' } });
    watch(
      () => state.user.name, // 使用 getter 函数
      (newName) => { /* ... */ }
    );
    
  • 深层监听对象/数组

    watch(
      () => state.user,
      (newUser) => { /* ... */ },
      { deep: true } // 深度监听嵌套属性变化
    );
    
3. 配置选项
选项说明
deep: true深度监听对象/数组的内部变化
immediate: true立即触发回调(类似 Vue 2 的 immediate
`flush: ‘pre’‘post’
watch(
  source,
  callback,
  { deep: true, immediate: true, flush: 'post' }
);

watchEffect 的深度解析

1. 基本用法
import { watchEffect, ref } from 'vue';

const count = ref(0);

// 自动追踪依赖
watchEffect(() => {
  console.log(`count的值:${count.value}`);
});

count.value = 1; // 输出 "count的值:1"
2. 特点
  • 自动依赖追踪:回调函数中使用的响应式变量会被自动追踪。
  • 立即执行:初始化时立即运行一次。
  • 无需指定依赖:适合依赖多个响应式变量的场景。
3. 停止侦听器

通过调用返回的函数停止侦听:

const stop = watchEffect(() => { /* ... */ });
stop(); // 手动停止侦听
4. 清理副作用

在回调中返回一个清理函数,用于重置操作(如取消请求):

watchEffect((onCleanup) => {
  const timer = setTimeout(() => {
    // 异步操作
  }, 1000);

  onCleanup(() => clearTimeout(timer)); // 清理函数
});

使用场景对比

1. 使用 watch 的场景
  • 需要精确控制侦听的目标
  • 需要获取旧值进行比较。
  • 需要延迟执行(默认不立即执行)。
  • 需要深度监听对象/数组
2. 使用 watchEffect 的场景
  • 依赖多个响应式变量且不想逐个指定。
  • 需要立即执行回调(如初始化加载数据)。
  • 逻辑简单且依赖关系动态变化。

最佳实践与注意事项

1. 避免无限循环

在回调中修改被侦听的源数据可能导致无限循环:

// ❌ 错误示例
watch(count, (newVal) => {
  count.value = newVal * 2; // 触发再次侦听
});
2. 性能优化
  • 减少深度监听deep: true 对性能有影响,尽量明确侦听具体属性。
  • 合理使用 flushflush: 'post' 可确保回调在 DOM 更新后执行。
3. 异步操作处理
  • 使用 onCleanup 清理未完成的异步任务(如请求取消):

    watchEffect(async (onCleanup) => {
      const abortController = new AbortController();
      onCleanup(() => abortController.abort()); // 清理时取消请求
    
      const data = await fetch(url, {
        signal: abortController.signal
      });
    });
    

完整示例

示例 1:监听搜索关键词(防抖)
<script setup>
import { ref, watch } from 'vue';

const searchKeyword = ref('');
let timer = null;

watch(searchKeyword, (newKeyword) => {
  clearTimeout(timer);
  timer = setTimeout(() => {
    fetchResults(newKeyword); // 防抖处理
  }, 500);
});
</script>
示例 2:自动追踪窗口尺寸
<script setup>
import { watchEffect } from 'vue';

const windowWidth = ref(window.innerWidth);

watchEffect((onCleanup) => {
  const handleResize = () => {
    windowWidth.value = window.innerWidth;
  };
  window.addEventListener('resize', handleResize);

  onCleanup(() => {
    window.removeEventListener('resize', handleResize);
  });
});
</script>
API核心选择依据
watch需要明确侦听特定数据源,获取旧值,或需要延迟执行、深度监听时使用
watchEffect依赖多个动态数据源,需要立即执行,或依赖关系复杂时使用
http://www.dtcms.com/a/98431.html

相关文章:

  • 【SQL】MySQL基础2——视图,存储过程,游标,约束,触发器
  • 关于音频采样率,比特,时间轴的理解
  • ai 项目练习(一)
  • AI来了,新手如何着手学习软件开发?
  • 基于kafka的分布式日志收集平台项目(续)
  • AnimateCC基础教学:随机抽取获奖名单及奖品-V1.0原型版
  • 双非一本毕业测试工作一年想转C++开发,嵌入式Linux与音视频方向哪个方向更合适?
  • JavaScript使用
  • 浅拷贝或深拷贝js数组或对象的方法
  • 常用数据库
  • 使用 Docker Compose 在单节点部署多容器
  • C++ 变量与初始化详解(十五)
  • 【商城实战(100)】商城败局启示录:探寻成功的反方向
  • 【ChatBox】deepseek本地部署
  • 解决 Gradle 构建错误:Could not get unknown property ‘withoutJclOverSlf4J’
  • 【Linux笔记】进程间通信——匿名管道||进程池
  • Linux 系统部署Jump Server服务
  • 使用msmtp和mutt在CentOS上发送指定目录下的所有文件作为邮件附件
  • 聚焦高德开放平台的地图应用场景:创新实践与技术解析
  • 若依赖前端处理后端返回的错误状态码
  • 【新手初学】SQL注入getshell
  • 1、C51单片机(STC8G2K64S4)串口实验
  • Java开发者指南:深入解析PBFT拜占庭容错算法
  • pycharm终端操作远程服务器
  • 【磁盘扩容】linux磁盘扩容
  • Koordinator-Metric查询
  • Python3基础库入门(个人学习用)
  • [ C语言 ] | 从0到1?
  • Redis设计与实现-哨兵
  • 分销商城小程序开发六大核心功能详解