4.5 计算属性与侦听器


4.5 计算属性与侦听器

本节摘要:计算属性(computed)缓存派生值,侦听器(watch)在数据变化时执行副作用。前者的价值是"按需重算 + 缓存",后者是"变化即响应"。两者分工稍异,本节把"什么时候用谁"讲清,避免新手见因果就用 watch 的常见绕路。

本节阅读目标
阅读完本节,你应当能够:

  1. 用 computed 计算派生值并理解它的缓存机制。
  2. 用 watch 侦听数据变化并触发副作用。
  3. 判断场景该用计算属性还是侦听器。

一、派生值:不该重复计算的输出

常常遇到这种需求:显示某数组的总价、过滤后的列表。这些值都能由现有数据推出来——派生值。最坏的做法是每次渲染都人工算,或在方法里重算。Vue 用 computed 专管这类"由数据派生、还会被复用"的值。

<script setup> import { ref, computed } from 'vue'; const cart = ref([{ price: 20 }, { price: 35 }]); const total = computed(() => cart.value.reduce((s, i) => s + i.price, 0)); </script> <template>合计:{{ total }}</template>

computed 只在它依赖的数据变化时才重算,不依赖的数据变了,它会直接返回缓存。这让派生值既准确又省算力。

二、侦听器:数据变了要去做事

computed 管"派生计算",watch 管"变化后的副作用"——切入点是"数据变了,我要去做什么"(比如发请求、写存储、更新别的 UI)。区别在于 watch 的落脚点是动作而不是返回值。

<script setup> import { ref, watch } from 'vue'; const key = ref(''); watch(key, (newVal, oldVal) => { console.log('关键词从', oldVal, '变成', newVal); }); </script>

当"别的状态需要跟着动"时,watch 是明确工具;而"只要显示派生结果"应优先 computed。

三、一场实际的取舍:缓存要不要、动作往哪落

新手最常见的绕路是"看到要随输入变化的东西,就条件反射写 watch"。下面这个场景最能说明差别:一个搜索框,下面要实时显示"匹配条数",同时希望在关键词变化时调一次后端接口做联想。

"匹配条数"是典型派生值,用 computed 最合适——它只取决于当前列表,被模板直接引用,还能享受缓存:

<script setup> import { ref, computed } from 'vue'; const kw = ref(''); const all = ref(['林', '月', '风', '云']); const matched = computed(() => kw.value ? all.value.filter((x) => x.includes(kw.value)) : all.value ); </script> <template> <p>匹配 {{ matched.length }} 条</p> </template>

而"触发一次联想请求"是副作用,必须用 watch——因为它的落点是"去请求",不是"返回一个值"。要是你用 computed 去做请求,computed 的缓存与"仅在渲染被读时才求值"的特性,会让这个请求时机变得不可预测、还为复用它的组件带来实打实的隐形重复调用。判据始终是那条:取一个值用 computed,做一件事用 watch

四、一张判断表

需求 该用什么
我的数据派生一个值给界面显示 computed
数据从几个源拼出一个新值 computed
数据变了我要发起请求 / 写存储 / 改别的 watch
我要监听旧值新值对比后决定 watch

通俗记忆:要算就用 computed,要动就用 watch。拿不准先问"我想取一个值,还是想干一件事"。

五、图:computed 与 watch 的分工

图:计算属性与侦听器的职责分界

图:计算属性与侦听器的职责分界

六、常见坑

  • 想取派生值却写 watch:watch 不返回可展示值给模板,绕一圈还要再存一个 state,常说这是把简单事做复杂。
  • computed 里做副作用:计算属性应保持纯——只在它里面做计算,别偷偷改别的状态,会引入不可预测。
  • watch 忘了需要的依赖:平铺多个依赖或 deep 配置,容易漏掉想监听的变化。

七、当"取一个值"和"做一件事"同时都在

真实组件里,computed 与 watch 经常同框出现,判据依然管用,但要再明一层"谁先谁后、谁依赖谁"。仍以上面的搜索框为例:matched 是一个 computed——它只读当前列表与关键词,自给自足,谁引用它显示结果;而"关键词一变就去请求联想"则是一个 watch——它的触发依赖 kw 变化,落点是执行异步请求,不是算出值。

把它们摆到一起,最该避免的是"用 computed 递数据、用 watch 重新算同一份值"这种重复劳动。正确分工是:**

  • computed / 派生值给模板显示:
  • watch 只盯"要被动改变的外界动作"(请求、存储、切换、联动)。

凡是"由现有数据能直接推出来"的东西,都交给 computed,watch 越少背"翻译数据为界面"的锅,副作用就越聚焦、越可控。反之,如果某处用了 watch 还把派生结果再塞回一个 state 去显示,那通常意味着这一步本该是 computed 的差事。基准还是那句算与动的分别——只是当两者都在时,把它并列看,能让边界一眼更清。

本节要点回顾

  • computed:缓存派生值,依赖变才重算,适合显示用。
  • watch:数据变就去干事,适合副作用。
  • 判断口诀:取用 computed,动用 watch。
  • 两个坑:别用 watch 取派生值、别在 computed 里做副作用。

数据与派生都讲完,Vue 入门线的最后一块是事件与表单。v-model 双向绑定怎么处理用户输入,下一节收官本章。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U