计算属性可通过返回对象实现“多值返回”,各字段共享依赖、同步更新,适用于筛选统计等成套场景,避免重复计算和失去缓存。

计算属性本身只返回一个值,但这个值可以是对象——所以“多值返回”本质上是返回一个结构化对象,里面包含多个字段,每个字段代表一项计算结果。
用对象字面量直接返回多字段结构
在 computed 中直接返回一个对象,把不同维度的统计或派生值作为属性写进去。所有属性共享同一组依赖,响应式更新时整个对象会重新生成(但内部字段仍可被独立访问)。
- 适合:筛选+计数+分组摘要等需要成套展示的场景
- 关键点:对象里每个字段都应基于当前响应式状态计算,不额外调用方法、不缓存中间数组
- 示例:商品列表筛选面板中同时需要命中数、平均价格、最高分品牌
代码示意:
Vuejs
Vue.js 官方推荐通过 npm 进行安装,这是构建现代化前端项目最主流的方式。在终端中执行 npm install vue 即可获取最新稳定版,如需指定版本可添加 @版本号,例如 npm install vue@3.4.0。安装前请确保已配置 Node.js 环境(推荐 v18 及以上版本),并建议将 npm 镜像源切换至国内镜像以提升下载速度。对于大型项目,还可通过 npm create v
下载
<script setup><br>
import { ref, computed } from 'vue'<br>
const list = ref([/* 商品数组 */])<br>
const keyword = ref('')<br>
const category = ref('')<br>
const minPrice = ref(null)<br><br>
const stats = computed(() => {<br>
const filtered = list.value.filter(item => {<br>
const matchKeyword = !keyword.value || item.name.includes(keyword.value)<br>
const matchCategory = !category.value || item.category === category.value<br>
const matchPrice = minPrice.value == null || item.price >= minPrice.value<br>
return matchKeyword && matchCategory && matchPrice<br>
})<br><br>
return {<br>
count: filtered.length,<br>
avgPrice: filtered.length ? (filtered.reduce((a, b) => a + b.price, 0) / filtered.length).toFixed(2) : 0,<br>
topBrand: filtered.length ? filtered.reduce((a, b) => (a.sales || 0) > (b.sales || 0) ? a : b).brand : '-' <br>
}<br>
})<br>
</script>模板中按需解构使用,无需重复计算
模板里可以直接用 {{ stats.count }}、{{ stats.avgPrice }} 等,Vue 会正确追踪到 stats 对象整体的依赖关系;只要 list 或任一筛选条件变化,stats 就重算一次,所有字段同步更新。
- 避免拆成多个 computed(如 count、avgPrice 各自定义),否则 filter 逻辑重复执行,性能浪费
- 也不建议在 template 里用 methods 调用函数,失去缓存能力
- 如果某字段计算开销极大且不常显示,可考虑单独抽离为独立 computed,但需评估必要性
注意响应式穿透与只读限制
computed 返回的对象默认是响应式的,但它是只读快照——你不能直接修改 stats.count = 100,这不会触发更新,也不会影响源数据。
- 如需双向联动(比如点击“清空筛选”要重置 stats 内部某个字段),应操作原始 ref(如 keyword.value = ''),而非试图改写 stats
- 若真需要可写的嵌套结构,得用 reactive + 自定义 setter 逻辑,但多数统计场景不需要
大数据量时的小优化提示
当 list 数据量大(如上万条),filter 每次都全量遍历成本高。可提前对常用筛选字段做索引映射(如 categoryMap、priceBuckets),或用 computed 缓存预处理结果,再在 stats 中复用。
- 例如:预先 computed 一个 indexedList,按 category 分组;stats 中直接查对应组长度,比每次 filter 快得多
- 避免在过滤中用正则或复杂函数,尤其在高频交互场景下