计算属性和watch应职责分离:computed用于同步、可缓存的派生值,如格式化、过滤;watch用于执行副作用,如请求、存储更新;二者可协同,watch监听computed结果以实现精准响应。
计算属性和 watch 各有分工,强行混用反而容易引发重复计算或副作用误触发。关键不是“结合”,而是按职责分离:用 computed 处理同步、可缓存的派生值,用 watch 处理需要响应变化并执行副作用的操作。
计算属性负责派生与缓存
当某个值由其他响应式数据推导而来,且逻辑是纯函数(无 API 调用、无 DOM 修改、无状态变更),就该用 computed。
- 它自动追踪依赖,只在依赖变化时重新求值
- 结果会被缓存,多次访问不重复执行函数体
- 适合格式化文本、拼接字段、过滤列表、计算布尔状态等
watch 负责响应与执行
当数据变化需要发起请求、更新本地存储、重置表单、触发动画或调用第三方 SDK,这些有“副作用”的操作必须交给 watch。
- watch 不缓存,每次变化都执行回调(除非手动节流)
- 支持 immediate(立即执行)、deep(深度监听)、handler + 参数解构等精细控制
- 避免在 watch 中直接赋值给另一个响应式变量再用 computed 读取——这会绕过响应链,还可能造成循环
典型错误:用 watch 替代 computed
比如把用户名全名拼接写在 watch 里:
- firstName 或 lastName 一改就触发拼接,哪怕只是输入中途
- 没有缓存,连续输入十个字符可能触发十次拼接
- 正确做法是定义 computed fullName,模板直接用 {{ fullName }}
协同场景:watch 监听 computed 的结果
computed 本身也可作为 watch 的监听源——尤其当你只关心“最终结果是否变化”,而非原始字段细节时:
- 例如搜索条件组合成 query 对象,用 computed 生成规范化后的 searchParams
- 再用 watch 监听 searchParams,仅在其真正变化时调用 API
- 这样既利用了 computed 的缓存和组合能力,又让副作用精准可控