关于vue3 watch 第一个参数源码内部的处理方式

news/2025/2/9 13:59:47/文章来源:https://www.cnblogs.com/is-DW/p/18706092

以下是 Vue 3 watch 第一个参数的一切形式和最终转换形态的完整解析:


核心结论

在 Vue 3 中,watch 第一个参数的所有形式最终都会被统一转换成

  1. 一个 getter 函数(当侦听单个来源时)
  2. 由 getter 函数组成的数组(当侦听多个来源时)

这是通过 Vue 源码中的 doWatch 方法完成的标准化转换。


各类形式的实际转换

1. Ref 引用

const count = ref(0)// 🌟 转换过程:
watch(count, callback) → 被转换为:
watch(() => count.value, callback)

2. Reactive 对象

const state = reactive({ a: 1 })// 🌟 转换过程:
watch(state, callback) → 被转换为:
watch(() => state, callback, { deep: true })

Vue 会自动给响应式对象附加 deep: true 选项。

3. 计算属性

const double = computed(/* ... */)// 🌟 转换过程:
watch(double, callback) → 被转换为:
watch(() => double.value, callback)

4. Getter 函数

watch(() => obj.a + obj.b, callback
)
// 🌟 直接作为 getter 函数使用,无需转换

5. 数组形式

watch([refA, () => obj.b, reactiveObj],callback
)
// 🌟 转换后的等效形式:
[() => refA.value,        // ref → .value() => obj.b,             // getter 直接保留() => reactiveObj        // reactive自动+deep
]
// 并给整个 watch 添加 deep: true(因包含 reactive 对象)

源码级验证

vue@3.4.27doWatch 函数为例(关键片段):

处理入口

文件位置:packages/runtime-core/src/apiWatch.ts

function doWatch(source: WatchSource | WatchSource[] | object, // 接受所有可能的来源类型cb: WatchCallback | null,options: WatchOptions
) {// 关键转换逻辑...
}

类型分支处理

// 分支 1:处理响应式对象(Reactive)
if (isReactive(source)) {getter = () => source;deep = true; // 🔥自动启用深度侦听
}// 分支 2:处理 Ref
else if (isRef(source)) {getter = () => source.value;
}// 分支 3:处理函数(Getter)
else if (isFunction(source)) {getter = source;
}// 分支 4:处理数组类型
else if (isArray(source)) {getter = () =>source.map(s => {if (isRef(s)) {return s.value;} else if (isReactive(s)) {return traverse(s); // 🔥遍历并深度响应} else if (isFunction(s)) {return s();}});
} // 分支 5:错误类型处理
else {warn('Invalid watch source');
}

转换过程可视化

原始类型              ⇒ 标准化后的 getter 形式
───────────────────────────────────────────────
ref                ⇒ () => ref.value
reactive           ⇒ () => reactiveObj + deep=true
computed           ⇒ () => computed.value
function           ⇒ 原样保留
array              ⇒ [()=>item1.val, ()=>item2.val...]
普通对象            ⇒ 抛出警告(非法类型)

为什么需要这种转换?

  1. 统一依赖跟踪:无论数据来源如何,Vue 的响应式系统(effect)最终都需要通过 getter 函数来追踪依赖。
  2. 深层次监听reactive 对象需要自动开启 deep 以监听嵌套变化。
  3. 性能优化:对 Ref 的值访问(.value)需在 getter 中捕获才能触发响应式。
  4. 数组支持:保证多个源变更时能统一触发回调。

示例:实际等价转换

// 用户编写的代码
watch([refObj, reactiveObj, () => computedVal.value],([refNew, reactiveNew, computedNew]) => {...},{ deep: true }
)// Vue 实际运行的等价逻辑:
const getters = [() => refObj.value,() => reactiveObj,       // 自动触发 deep() => computedVal.value
];effect(() => {const values = getters.map(get => get());// 跟踪所有依赖...
});

转换的实际意义

  1. 代码简化:允许开发者用最直观的方式传递侦听源。
  2. 性能深度控制:默认对 reactive 自动启用深度监听,其他类型按需处理。
  3. 泛用性支持:让数组/单源的逻辑能复用同一套响应式机制。

重要边界情况

  1. 深度监听优先级
    watch(reactiveObj, callback, { deep: false }) 
    // 即便手动设置 deep: false,Vue 依然会强制为 true
    
  2. 普通对象非法
    watch({ a: 1 }, callback) // ❌ 控制台警告
    

这些处理机制让 Vue 的 watch 在保持简洁 API 的同时,底层实现了响应式系统的统一管理。理解这些转换规则有助于写出更高效和可预测的侦听逻辑。

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

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

相关文章

销售就是推销自己

销售的本质是顾客用钱买满足自己需求的卖方提供的产品。销售员就承担着桥梁的角色。渠道那么多,销售人员那么多,顾客为什么要通过你来买? 优秀的销售人员(商人)有下面几个特点。 1.自信 如果你相信你会成功,成功便会发生;如果你相信你会失败,失败便会找上门。无论如何我…

Snipaste - 截屏软件

qq截屏闪退,故更改软件————下载https://www.snipaste.com/download.html选择对应版本 下载后双击即可(默认F1截屏) 参考: https://blog.csdn.net/m0_64979660/article/details/142353087

红蓝对抗之系统密码提取

mimikatz mimikatz工具从内存中提取明文密码,HASH值,PIN密码和票据,利用zerologon漏洞(通过NetLogon/MS-NRPC协议与AD域控建立安全通道时,可利用该漏洞将AD域控的计算机账号密码设置为空。 mimikatz 需要管理员或 SYSTEM 权限,通常使用 DEBUG 权限执行某些操作,与 LSASS…

wsl启动报错Cannot execute daemonize to start systemd的解决方法

WSL 启动报错 "Cannot execute daemonize to start systemd" 的解决方法 问题背景 在启动 WSL2 时遇到以下错误: Cannot execute daemonize to start systemd解决思路来源:https://github.com/DamionGans/ubuntu-wsl2-systemd-script/issues/37此错误通常是因为 dae…

2.2-2.9做题笔记

2.2 - 2.9 做题笔记 最近一周做的所有题目,包括 cyezoj 上的模拟赛,专题作业和 ABC。 2.4 CYEZ SHOI2025 模拟测试七 CYEZ 404 过桥 题目难度:省选 D1T1 赛时:20pts ;订正:100pts 大意 有 \(n\) 个人要过一座每次最多容 \(c\) 人通过、且仅有一只手电的一座桥。多人同时过…

【烂笔头系列】计算广告笔记16-其他广告相关技术

创意优化 创意需要将向用户推送广告的关键原因明确表达出来 程序化创意地域性创意 搜索重定向创意 个性化重定向创意电机热力图电机热力图是将某一个创意各位置被点击的密度用热力图方式呈现,帮助创意优化者直观的发现和解决其中的问题创意的发展趋势视频化激励视频形式交互化…

【烂笔头系列】推荐系统笔记10-经典深度学习推荐模型

特征组合和特征交叉问题非常常见,特征的种类非常多,特征交叉的复杂程度也要大得多。解决这类问题的关键,就是模型对于特征组合和特征交叉的学习能力,因为它决定了模型对于未知特征组合样本的预测能力,而这对于复杂的推荐问题来说,是决定其推荐效果的关键点之一。 那特征交…

【烂笔头系列】推荐系统笔记09-深度学习推荐模型发展脉络

1. 深度学习模型拟合能力更强 特征交叉方式中,点积等方式过于简单,在样本数据比较复杂的情况下,容易欠拟合。而深度学习可以大大提高模型的拟合能力,比如在 NeuralCF(神经网络协同过滤)模型中,点积层被替换为多层神经网络,理论上多层神经网络具备拟合任意函数的能力,所…

【烂笔头系列】推荐系统笔记12-模型评估

1. 离线评估 (1)介绍 离线评估是最常用、最基本的。顾名思义就是:我们将模型部署于线上环境之前,在离线环境下进行的评估。由于不用部署到生产环境,“离线评估”没有线上部署的工程风险,也不会浪费宝贵的线上流量资源,而且具有测试时间短,可多组并行,以及能够利用丰富…

【烂笔头系列】推荐系统笔记05-Embedding技术

1. Embedding是什么 Embedding 就是用一个数值向量“表示”一个对象(Object)的方法解读1:左边例子,从 king 到 queen 的向量和从 man 到 woman 的向量,无论从方向还是尺度来说它们都非常接近。 解读2:右边例子也很典型,从 walking 到 walked 和从 swimming 到 swam 的向…

【烂笔头系列】推荐系统笔记04-推荐系统有哪些可以利用的特征

1. 特征与工程 (1)特征就是对具体行为的抽象,但是抽象过程会造成信息的损失 ① 因为具体的推荐行为和场景中包含大量原始的场景、图片和状态信息,保存所有信息的存储空间过大,我们根本无法实现。 ② 因为具体的推荐场景中包含大量冗余的、无用的信息,把它们都考虑进来甚至…

1.AI 大模型的基本概念

1.目前AI 行业分类 2023年, AI 分 传统AI(机器学习、深度学习、强化学习) AI算法工程师 AI大模型(AI2.0)神经网络,自注意机制,Transform机制 AI应用开发工程师 2.什么是AI 大模型(LLM) 参数大,训练的数据集大 3.AI大模型最终价值 TOB 和 TOC 的应用 4.A…