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

Vue3中computed和watch的区别

文章目录

  • 前言
    • 🔍 一、`computed` vs `watch`
      • ✅ 示例对比
        • 1. `computed` 示例(适合模板绑定、衍生数据)
        • 2. `watch` 示例(副作用,如调用接口)
    • 🧠 二、源码实现原理(简化理解)
      • 1. `computed` 原理
      • 2. `watch` 原理
    • 📌 三、使用建议
    • 扩展:
    • 🧠 四、Vue 3 响应式系统核心:`effect` / `track` / `trigger`
      • 1. `effect(fn)`:响应式副作用收集器
      • 2. `track(target, key)`:依赖追踪
      • 3. `trigger(target, key)`:依赖触发
      • 🔁 总结:响应式机制流程
    • 🔁 五、`watchEffect` 是什么?
      • 🌟 特点:
      • 📦 内部工作机制(简化版)
    • 🧪 应用场景对比
    • ✅ 实战案例:watch vs watchEffect
      • `watch` 示例(明确监听)
      • `watchEffect` 示例(更简洁)


前言

Vue 3 中 computedwatch区别源码实现逻辑(Composition API 版本)。


🔍 一、computed vs watch

项目computedwatch
类型派生状态(缓存)响应式副作用
用途根据已有响应式变量派生出新数据监听某个响应式数据的变化后执行副作用逻辑
是否缓存✅ 是❌ 否
返回值Ref(值类型)void(返回值无意义)
使用场景显示用、模板绑定API 调用、定时器、调试、数据同步等

✅ 示例对比

1. computed 示例(适合模板绑定、衍生数据)
const price = ref(100)
const tax = ref(0.1)const total = computed(() => price.value * (1 + tax.value))
// total.value = 110
2. watch 示例(副作用,如调用接口)
watch(price, (newVal, oldVal) => {console.log(`价格变化:${oldVal} -> ${newVal}`)// 比如向服务器汇报价格变动
})

🧠 二、源码实现原理(简化理解)

1. computed 原理

  • Vue 内部使用了 effectRef 实现 computed
  • 默认是 lazy effect,只有在访问 .value 时才执行计算。
  • Vue 自动追踪依赖(依赖收集),只在依赖变化时重新执行。
function computed(getter) {const result = ref()const runner = effect(getter, {lazy: true,scheduler: () => {dirty = true}})return {get value() {if (dirty) {result.value = runner()dirty = false}return result.value}}
}

关键点:缓存 + 懒执行 + 自动依赖追踪


2. watch 原理

  • watch 是对 effect 的进一步封装。
  • 内部会递归地跟踪传入的响应式数据,建立响应关系。
  • 依赖变动时,会执行用户提供的回调函数。
function watch(source, cb) {let oldValue = source()effect(() => {const newValue = source()if (newValue !== oldValue) {cb(newValue, oldValue)oldValue = newValue}})
}

关键点:不缓存 + 只执行副作用 + 深层依赖可配置


📌 三、使用建议

需求推荐
只用来展示(派生数据)computed
需要执行副作用(发请求、console.log、同步)watch
复杂对象监听watch 配合 deep: true
多个数据合并监听watch([a, b])

扩展:

  • watchEffect 的解释
  • 或深入理解 Vue 的响应式核心 effecttracktrigger 机制

继续深入讲解 Vue 3 响应式系统的核心:effecttracktrigger,并说明 watchEffect 是如何工作的。


🧠 四、Vue 3 响应式系统核心:effect / track / trigger

1. effect(fn):响应式副作用收集器

  • 用于包裹副作用函数(如 computed 的 getter 或 watch 的监听函数)。
  • 在函数中读取响应式数据时,会被自动“追踪依赖”。
effect(() => {console.log(state.count)  // 依赖 `state.count`
})

2. track(target, key):依赖追踪

  • 当你读取响应式对象的属性时,会触发 track
  • track 会记录当前活跃的 effect,让这个 effect 依赖这个属性。
// 简化版
function track(target, key) {if (!activeEffect) returnlet depsMap = targetMap.get(target)if (!depsMap) {depsMap = new Map()targetMap.set(target, depsMap)}let deps = depsMap.get(key)if (!deps) {deps = new Set()depsMap.set(key, deps)}deps.add(activeEffect)
}

3. trigger(target, key):依赖触发

  • 当你修改响应式数据时,会触发 trigger
  • 它会找到依赖这个属性的所有 effect,然后重新执行它们。
function trigger(target, key) {const depsMap = targetMap.get(target)if (!depsMap) returnconst effects = depsMap.get(key)effects.forEach(effect => effect())
}

🔁 总结:响应式机制流程

  1. effect(fn) 执行时读取响应式数据 → track 收集依赖
  2. 数据变化时 → trigger 调用依赖的 effect → 重新执行

🔁 五、watchEffect 是什么?

🌟 特点:

  • 类似 computed,但用于副作用。
  • 自动收集依赖,无需显式声明。
  • 依赖变更时自动重新执行副作用函数。
watchEffect(() => {console.log(`count 是 ${count.value}`)
})

📦 内部工作机制(简化版)

function watchEffect(effectFn) {const runner = effect(effectFn)return () => stop(runner)
}
  • watchEffect 调用时立即执行 effectFn
  • 响应式依赖被收集。
  • 当依赖变更时,会重新调用 effectFn
  • 返回的函数可用于停止监听。

🧪 应用场景对比

需求场景推荐工具
计算派生值computed
副作用 + 明确监听字段watch
副作用 + 自动依赖收集watchEffect

✅ 实战案例:watch vs watchEffect

watch 示例(明确监听)

watch(() => user.id, (newId) => {fetchUserDetail(newId)
})

watchEffect 示例(更简洁)

watchEffect(() => {fetchUserDetail(user.id)
})

http://www.lryc.cn/news/2404644.html

相关文章:

  • 发版前后的调试对照实践:用 WebDebugX 与多工具构建上线验证闭环
  • 瀚文(HelloWord)智能键盘项目深度剖析:从0到1的全流程解读
  • Shell编程核心符号与格式化操作详解
  • 针对“仅某个地区出现Bug”的原因分析与解决方案
  • 学习STC51单片机30(芯片为STC89C52RCRC)
  • sql中group by使用场景
  • 将HTML内容转换为Canvas图像,主流方法有效防止文本复制
  • Python-进程
  • Paraformer分角色语音识别-中文-通用 FunASR demo测试与训练
  • 【从0-1的CSS】第1篇:CSS简介,选择器以及常用样式
  • 对抗反爬机制的分布式爬虫自适应策略:基于强化学习的攻防博弈建模
  • JDK21深度解密 Day 15:JDK21实战最佳实践总结
  • 手写muduo网络库(一):项目构建和时间戳、日志库
  • 每日算法刷题Day25 6.7:leetcode二分答案3道题,用时1h40min(遇到两道动态规划和贪心时间较长)
  • 14-Oracle 23ai Vector Search 向量索引和混合索引-实操
  • kubeadm安装k8s
  • 服务器新建用户无法使用conda
  • Web前端基础:JavaScript
  • 基于对比学习的带钢表面缺陷分类研究,整合SimCLR自监督预训练与YOLOv8目标检测框架的技术解析及Python实现方案
  • 基于AWS Serverless架构:零运维构建自动化SEO内容生成系统
  • 【.net core】天地图坐标转换为高德地图坐标(WGS84 坐标转 GCJ02 坐标)
  • Linux操作系统故障应急场景及对应排查方法
  • 电镀机的阳极是什么材质?
  • vscode调试deepspeed的方法之一(无需调整脚本)
  • 神经网络-Day44
  • 创客匠人:如何通过精准定位实现创始人IP打造与知识变现
  • Codeforces Round 509 (Div. 2) C. Coffee Break
  • 榕壹云健身预约系统:多门店管理的数字化解决方案(ThinkPHP+MySQL+UniApp实现)
  • QUIC——UDP实现可靠性传输
  • 提高Python编程效率的工具推荐