跳到正文

Vue 计算属性与侦听器 ​

  • 状态:未准备
  • 适用方向:前端 / Go 全栈
  • 最近复习:待填写
  • 下次复习:待安排

一句话回答 ​

computed 用于缓存同步派生值,watch 显式监听来源并执行副作用,watchEffect 自动追踪同步执行阶段读取的依赖;异步请求必须处理失效与取消。

原理解释 ​

方式依赖与执行适用场景
computed自动追踪 getter 读取,按需求值并缓存筛选、汇总、展示值
watch显式指定 ref、getter、响应式对象或来源数组,默认惰性请求、持久化、对比新旧值
watchEffect立即执行,自动追踪同步读取多个关联依赖驱动的外部同步

computed getter 应保持纯净,不发请求或修改其他状态;普通方法每次调用都会执行,computed 可以复用依赖未变时的结果。没有响应式依赖的 Date.now 不会因为时间流逝自动让计算属性重算。

ts
import { ref, computed, watch } from 'vue'

const keyword = ref('')
const items = ref([{ id: 1, title: 'Vue' }])
const visible = computed(() =>
  items.value.filter(item => item.title.includes(keyword.value)),
)
const result = ref<unknown>(null)
const error = ref<string | null>(null)

watch(keyword, async (query, _old, onCleanup) => {
  const controller = new AbortController()
  let active = true
  onCleanup(() => { active = false; controller.abort() })
  error.value = null
  try {
    const response = await fetch(`/api/search?q=${encodeURIComponent(query)}`, {
      signal: controller.signal,
    })
    if (!response.ok) throw new Error(`HTTP ${response.status}`)
    const data: unknown = await response.json()
    if (active) result.value = data
  } catch (cause) {
    if (active) error.value = String(cause)
  }
}, { immediate: true })

清理在本次 watcher 失效时执行;先注册清理,再等待请求。active 阻止旧结果写回,abort 尽量取消工作。实际业务还需 loading、数据校验和缓存策略。

场景与边界 ​

  • watch(() => state.count, ...) 监听属性;直接传 state.count 得到的是普通值,不是有效响应式来源。
  • 直接 watch reactive 对象会隐式深层监听;watch 返回对象的 getter 通常需 deep 才追踪嵌套修改。深层原地变更时 newValue/oldValue 可能是同一对象,不会自动生成历史快照。
  • watchEffect 的异步回调只追踪首次 await 前同步访问的依赖,await 后首次读取的值不会因此被收集。
  • 默认 watcher 回调在自身组件 DOM 更新前执行;读取更新后的 DOM 可用 flush:'post'。flush:'sync' 不批处理,应谨慎用于高频变更。
  • Vue 3.5+ 的 onWatcherCleanup 必须同步注册,不能在 await 后调用;示例使用回调参数 onCleanup,兼容更广的 Vue 3 版本。

项目中的应用 ​

目前没有 Vue 源码证据。可对照 请求竞态与实时通信 将搜索竞态写成 watch 版本,控制返回顺序验证旧结果不会覆盖新查询。

常见追问 ​

  • watch 能代替 computed 吗? 技术上可维护另一份状态,但会增加同步分支;纯派生值优先 computed。
  • deep 一定更好吗? 深遍历有成本,应明确监听字段;Vue 3.5+ 还支持数值深度上限,需核对目标版本。
  • immediate 与 watchEffect 等价吗? 不等价,前者仍使用显式来源,不把回调中的所有读取当来源。

参考资料 ​

理解机制,讲清取舍,用复盘检验掌握。