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

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.xdnf.cn/news/12666.html

相关文章:

  • OpenLayers 导航之运动轨迹
  • 深入剖析 RocketMQ 中的 DefaultMQPushConsumerImpl:消息推送消费的核心实现
  • Docker基础(二)
  • TTL简述
  • Unity基础-欧拉角和四元数
  • 【Elasticsearch】映射:Join 类型、Flattened 类型、多表关联设计
  • 基于springboot的藏文古籍系统
  • Nature子刊:16S宏基因组+代谢组学联动,借助MicrobiomeGS2建模揭示IBD代谢治疗新靶点
  • Java高级 | 【实验六】Springboot文件上传和下载
  • Python 中的MVC与MVP 框架与示例
  • LVGL对显示接口的要求
  • 闲庭信步使用SV搭建图像测试平台:第一课——图片的读写
  • 【商城saas和商城源码的区别】
  • 【Zephyr 系列 13】BLE Mesh 入门实战:构建基础节点通信与中继组播系统
  • 类型别名与类型自动推导
  • Redis数据持久化之RDB快照
  • 【走好求职第一步】求职OMG——见面课测验4
  • SAP学习笔记 - 开发27 - 前端Fiori开发 Routing and Navigation(路由和导航)
  • 算术图片验证码(四则运算)+selenium
  • 【大模型】大模型RAG(Retrieval-Augmented Generation)面试题合集
  • 欢乐熊大话蓝牙知识16:蓝牙是怎么找设备的?扫描与广播的“对话内幕”
  • Shell编程精髓:表达式与数组实战指南
  • DbServer链接KingBase8(人大)数据库
  • Android座舱系统Agent改造方案
  • day 47
  • 微前端架构下的B端页面设计:模块化与跨团队协作的终极方案
  • Python爬虫-爬取各省份各年份高考分数线数据,进行数据分析
  • 国产pcie switch,支持PCIE 3.0/4.0/5.0,支持昇腾310/910 GPU,支持龙芯、海光、飞腾
  • 小白成长之路-Linux Shell脚本练习
  • 2025年- H77-Lc185--45.跳跃游戏II(贪心)--Java版