应使用 watcheffect 实现购物车选中项金额汇总,因其能响应式监听 checked、price、count 变化并自动重算,适合需同步 localstorage 或埋点等副作用场景;而 computed 更适用于模板直接显示的声明式求值。

用 watchEffect 自动计算购物车选中项的合计数额,核心不是“算总和”,而是“响应式地监听选中状态变化并触发重新汇总”。它适合在逻辑较轻、依赖关系明确、且不需要缓存结果的场景下替代 computed —— 比如你只关心“当前哪些商品被勾选了”,而总价只是副作用输出(例如同步更新 localStorage 或发送埋点)。
watchEffect 与 computed 的关键区别
computed 是“声明式求值”:你定义一个公式,Vue 自动缓存、追踪依赖、返回响应式值;
watchEffect 是“副作用驱动”:你写一段执行逻辑,Vue 在依赖变化时自动重跑这段逻辑,不返回值,也不缓存。
- 如果你要在模板里直接显示合计金额 → 优先用 computed
- 如果你需要在选中变化时做额外动作(比如保存到本地、发请求、更新 UI 状态)→ watchEffect 更自然
- watchEffect 会立即执行一次,自动收集它内部读取的所有响应式依赖
如何用 watchEffect 实现选中项金额汇总
假设你的购物车数据结构如下:
const cartItems = ref([
{ id: 1, name: '苹果', price: 5.5, count: 2, checked: true },
{ id: 2, name: '牛奶', price: 12.0, count: 1, checked: false },
{ id: 3, name: '面包', price: 8.5, count: 3, checked: true }
])
你只需在 setup 中写:
import { ref, watchEffect } from 'vue'
<p>const selectedTotal = ref(0)</p><p>watchEffect(() => {
const sum = cartItems.value.reduce((acc, item) => {
if (item.checked) {
const price = parseFloat(item.price) || 0
const count = parseInt(item.count) || 0
return acc + price * count
}
return acc
}, 0)
selectedTotal.value = Number(sum.toFixed(2))
})</p>
这样,只要 cartItems 中任意 item.checked、price 或 count 改变,watchEffect 就会重新运行,selectedTotal 实时更新。
配合模板和交互使用
模板中可以直接绑定 selectedTotal:
<p>已选商品合计:¥{{ selectedTotal }}</p>
同时支持常见交互:
- 点击单个复选框 → item.checked 切换 → 触发 watchEffect 重算
- 全选按钮切换 → 批量修改所有 item.checked → 同样触发
- 数量输入框 v-model 绑定 item.count → 依赖被读取 → 自动重算
注意:如果 price 或 count 是字符串(如 "¥12.00"),需先提取数字,可用 item.price.toString().match(/[\d.]+/)?.[0] || '0'。
进阶:避免重复计算或副作用干扰
watchEffect 内部应只做“纯读取 + 赋值”,不要混入异步操作或 DOM 修改:
- ✅ 正确:更新 ref、调用 API(用 async/await 包裹)、写 localStorage
- ❌ 避免:直接修改 cartItems.value(可能引发循环触发)、在其中调用 this.$forceUpdate()
- 如需防抖或节流汇总,可结合 setTimeout 或 useDebounce(第三方库)
不复杂但容易忽略:watchEffect 的清理函数(onInvalidate)一般不用,除非你在里面发起未完成的异步请求,需要取消前序任务。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










