文章目录
-
- 一、核心特性(必看)
- 二、使用前提
- [三、组合式 API 写法(推荐,Vue3 主流)](#三、组合式 API 写法(推荐,Vue3 主流))
-
- [1. 基础用法:只读计算属性(最常用)](#1. 基础用法:只读计算属性(最常用))
- [2. 进阶用法:可写计算属性](#2. 进阶用法:可写计算属性)
- [四、选项式 API 写法(兼容 Vue2 写法)](#四、选项式 API 写法(兼容 Vue2 写法))
- [四、computed 核心优势:对比 methods](#四、computed 核心优势:对比 methods)
- 五、常见使用场景
- 六、注意事项
- 七、知识总结
computed 是 Vue3 核心的响应式计算属性 ,核心作用是:基于依赖的响应式数据自动计算出新值,且自带缓存(依赖不变,计算结果不会重复计算),比普通方法性能更高。

一、核心特性(必看)
- 依赖追踪 :只依赖响应式数据(
ref/reactive),依赖变化时自动重新计算 - 缓存机制:依赖不变时,多次访问直接返回缓存值(方法每次调用都会执行)
- 两种写法:只读(常用)、可写(极少用)
- 返回值 :必须
return计算结果
二、使用前提
Vue3 中使用 computed 必须从 vue 导入 ,支持 组合式 API(<script setup>) 和 选项式 API。
三、组合式 API 写法(推荐,Vue3 主流)
1. 基础用法:只读计算属性(最常用)
场景:根据响应式数据计算新值(如拼接字符串、数值计算、过滤数据)
vue
<template>
<div>
<!-- 直接使用计算属性,像普通变量一样 -->
<p>原始姓名:{{ firstName }} {{ lastName }}</p>
<p>完整姓名(computed):{{ fullName }}</p>
<p>年龄+1:{{ nextAge }}</p>
</div>
</template>
<script setup>
// 1. 导入 computed 和响应式API
import { computed, ref, reactive } from 'vue'
// 2. 定义响应式数据(依赖源)
const firstName = ref('张')
const lastName = ref('三')
const user = reactive({ age: 20 })
// 3. 定义计算属性:传入一个 getter 函数
const fullName = computed(() => {
// 依赖:firstName、lastName
return firstName.value + lastName.value
})
const nextAge = computed(() => {
// 依赖:user.age
return user.age + 1
})
</script>
2. 进阶用法:可写计算属性
计算属性默认只读 ,如果需要手动修改值,需要传入对象 (包含 get 和 set 方法)。
vue
<template>
<input v-model="fullName" placeholder="修改完整姓名">
<p>名:{{ firstName }} 姓:{{ lastName }}</p>
</template>
<script setup>
import { computed, ref } from 'vue'
const firstName = ref('张')
const lastName = ref('三')
// 可写计算属性
const fullName = computed({
// 读取时执行(和只读写法一致)
get() {
return firstName.value + ' ' + lastName.value
},
// 修改时执行:value 是你赋给 fullName 的新值
set(value) {
// 把新值拆分,反向修改依赖数据
const [first, last] = value.split(' ')
firstName.value = first || ''
lastName.value = last || ''
}
})
</script>
✅ 效果:修改输入框的 fullName,会自动同步更新 firstName 和 lastName。
四、选项式 API 写法(兼容 Vue2 写法)
如果是 Vue2 迁移到 Vue3,可以用这种写法:
vue
<template>
<div>{{ fullName }}</div>
</template>
<script>
export default {
data() {
return {
firstName: '李',
lastName: '四'
}
},
// 计算属性写在 computed 配置项中
computed: {
fullName() {
return this.firstName + this.lastName
}
}
}
</script>
四、computed 核心优势:对比 methods
很多新手会问:计算属性和方法有什么区别?
| 特性 | computed(计算属性) | methods(方法) |
|---|---|---|
| 缓存 | 依赖不变,缓存结果 | 每次调用都执行 |
| 性能 | 高(适合频繁使用的计算) | 低(适合一次性操作) |
| 使用方式 | 像变量一样直接用:{``{ fullName }} |
像方法一样调用:{``{ getFullName() }} |
示例:直观对比
vue
<template>
<!-- 多次使用,computed 只计算1次 -->
<p>{{ fullName }}</p>
<p>{{ fullName }}</p>
<!-- 多次使用,methods 执行3次 -->
<p>{{ getFullName() }}</p>
<p>{{ getFullName() }}</p>
</template>
<script setup>
import { ref, computed } from 'vue'
const firstName = ref('王')
const lastName = ref('五')
// computed:缓存
const fullName = computed(() => {
console.log('computed 执行了') // 只打印1次
return firstName.value + lastName.value
})
// methods:无缓存
const getFullName = () => {
console.log('methods 执行了') // 打印2次
return firstName.value + lastName.value
}
</script>
五、常见使用场景
- 字符串拼接/格式化:姓名、地址、日期格式化
- 数值计算:价格总和、折扣计算、数量统计
- 数据过滤/排序:列表筛选、数组排序
- 表单数据处理:表单验证、数据双向绑定格式化
实战示例:购物车总价计算
vue
<template>
<div>
<div v-for="item in cart" :key="item.id">
{{ item.name }}:{{ item.price }} × {{ item.count }}
</div>
<h3>总价:{{ totalPrice }} 元</h3>
</div>
</template>
<script setup>
import { computed, reactive } from 'vue'
// 购物车数据
const cart = reactive([
{ id: 1, name: '手机', price: 3999, count: 1 },
{ id: 2, name: '耳机', price: 299, count: 2 }
])
// 计算总价(自动依赖 cart,数据变化自动更新)
const totalPrice = computed(() => {
return cart.reduce((sum, item) => sum + item.price * item.count, 0)
})
</script>
六、注意事项
- 必须依赖响应式数据:如果依赖普通变量,计算属性不会自动更新
- 不要在 computed 中做异步操作 :计算属性是同步的,异步用
watch - 不要修改计算属性本身 :只读计算属性赋值会报警告,可写属性用
set修改 - 保持纯函数:计算属性只做计算,不修改外部数据、不产生副作用
七、知识总结
- 导入使用 :
import { computed } from 'vue',组合式 API 优先用 - 只读写法 :
const 变量 = computed(() => 计算结果) - 可写写法 :传入
{ get(){}, set(val){} }对象 - 核心优势 :自动缓存 + 响应式更新,性能远超普通方法
- 适用场景 :所有基于现有数据计算新值的场景