watch 与 computed:Vue3响应式的抉择

在 Vue 的响应式宇宙里,数据变化最终都会触发「副作用」:可能是重新渲染 DOM、发送网络请求,也可能是打印一条日志。Vue 提供了两条官方路线来捕获这些副作用------computedwatch。它们共享同一套依赖追踪引擎,却以截然不同的姿态服务于业务。

一、computed:把「结果」缓存成状态

想象你在做一份实时报表:销售额 = 单价 × 数量。只要单价或数量发生变化,报表必须立即更新,但你不希望每次模板读取都去重算一次。

ts 复制代码
const price = ref(100)
const count = ref(5)
const total = computed(() => price.value * count.value)

total 不是函数,而是一个「带缓存的 getter」。核心逻辑只有两步:

  • 首次读取 → 执行函数并将结果缓存;
  • 依赖变动 → 把缓存标记为「脏」,等待下一次读取时重新计算。

因此,total 永远同步、永远幂等、永远无副作用。它像数学公式一样纯粹,最适合放到模板里直接展示。

二、watch:把「动作」注册成回调

现在需求升级:当销售额首次超过 1000 时,弹一个提示,并向后端发一条记录。

这个动作需要「副作用」------弹窗与网络请求------这正是 watch 的舞台。

ts 复制代码
watch(total, (newVal, oldVal) => {
  if (newVal > 1000 && oldVal <= 1000) {
    alert('破千啦!')
    fetch('/api/record', { method: 'POST', body: newVal })
  }
})

watch 不关心结果,只关心「变化」。它把每一次变动封装成事件,允许你执行任意副作用:

  • 可以同步,也可以异步;
  • 可以读写 DOM,可以调用接口;
  • 不缓存任何结果,因为结果往往无法预测。

三、底层实现:同一条 effect,两种调度策略

无论是 computed 还是 watch,最终都会被包进同一个 effect 函数。差异体现在 调度器(scheduler):

  • computed 的调度器
ts 复制代码
  scheduler() {
    dirty = true            // 仅仅标记,不立即计算
    trigger(obj, 'value')   // 通知渲染函数
  }

它把真正的计算推迟到「下一次读取」,保证缓存生效。

  • watch 的调度器
ts 复制代码
  scheduler() {
    const newVal = effectFn()
    cb(newVal, oldValue)    // 立即执行用户回调
    oldValue = newVal
  }

它把最新值直接喂给用户回调,不缓存、不等待。

同一颗依赖追踪引擎,通过两个调度器分化出「缓存结果」与「立即动作」两条路径。

总结

用一句口诀:

  • 需要结果 → computed
  • 需要动作 → watch

具体场景举例:

  • 表单校验规则 ------ 用 computed,规则是数据推导;
  • 校验失败后高亮输入框 ------ 用 watch,高亮是副作用;
  • 根据路由参数计算面包屑 ------ 用 computed,面包屑是结果;
  • 路由变化后滚动到顶部 ------ 用 watch,滚动是动作。
相关推荐
木易 士心22 分钟前
Promise深度解析:前端异步编程的核心
前端·javascript
im_AMBER26 分钟前
Web 开发 21
前端·学习
又是忙碌的一天26 分钟前
前端学习day01
前端·学习·html
Joker Zxc30 分钟前
【前端基础】20、CSS属性——transform、translate、transition
前端·css
excel34 分钟前
深入解析 Vue 3 源码:computed 的底层实现原理
前端·javascript·vue.js
大前端helloworld1 小时前
前端梳理体系从常问问题去完善-框架篇(react生态)
前端
无敌最俊朗@1 小时前
C/C++ 关键关键字面试指南 (const, static, volatile, explicit)
c语言·开发语言·c++·面试
不会算法的小灰1 小时前
HTML简单入门—— 基础标签与路径解析
前端·算法·html
zero13_小葵司1 小时前
在Vue项目中构建后端配置的动态路由及权限控制体系
前端·javascript·vue.js
GISer_Jing1 小时前
前端框架篇——Vue&React篇
前端·javascript