Vue3 中 computed(计算属性)完整使用指南

文章目录

computed 是 Vue3 核心的响应式计算属性 ,核心作用是:基于依赖的响应式数据自动计算出新值,且自带缓存(依赖不变,计算结果不会重复计算),比普通方法性能更高。

一、核心特性(必看)

  1. 依赖追踪 :只依赖响应式数据(ref/reactive),依赖变化时自动重新计算
  2. 缓存机制:依赖不变时,多次访问直接返回缓存值(方法每次调用都会执行)
  3. 两种写法:只读(常用)、可写(极少用)
  4. 返回值 :必须 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. 进阶用法:可写计算属性

计算属性默认只读 ,如果需要手动修改值,需要传入对象 (包含 getset 方法)。

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,会自动同步更新 firstNamelastName


四、选项式 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>

五、常见使用场景

  1. 字符串拼接/格式化:姓名、地址、日期格式化
  2. 数值计算:价格总和、折扣计算、数量统计
  3. 数据过滤/排序:列表筛选、数组排序
  4. 表单数据处理:表单验证、数据双向绑定格式化

实战示例:购物车总价计算

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>

六、注意事项

  1. 必须依赖响应式数据:如果依赖普通变量,计算属性不会自动更新
  2. 不要在 computed 中做异步操作 :计算属性是同步的,异步用 watch
  3. 不要修改计算属性本身 :只读计算属性赋值会报警告,可写属性用 set 修改
  4. 保持纯函数:计算属性只做计算,不修改外部数据、不产生副作用

七、知识总结

  1. 导入使用import { computed } from 'vue',组合式 API 优先用
  2. 只读写法const 变量 = computed(() => 计算结果)
  3. 可写写法 :传入 { get(){}, set(val){} } 对象
  4. 核心优势自动缓存 + 响应式更新,性能远超普通方法
  5. 适用场景 :所有基于现有数据计算新值的场景
相关推荐
candyTong1 天前
一觉醒来,大模型就帮我排查完页面性能问题
前端·javascript·架构
魔术师Grace1 天前
我给 AI 做了场入职培训
前端·程序员
玩嵌入式的菜鸡1 天前
网页访问单片机设备---基于mqtt
前端·javascript·css
前端一小卒1 天前
我用 Claude Code 的 Superpowers 技能链写了个服务,部署前差点把服务器搞炸
前端·javascript·后端
滑雪的企鹅.1 天前
HTML头部元信息避坑指南大纲
前端·html
一拳不是超人1 天前
老婆天天吵吵要买塔罗牌,我直接用 AI 2 小时写了个在线塔罗牌
前端·ai编程
阿丰资源1 天前
SpringBoot+Vue实战:打造企业级在线文档管理系统
vue.js·spring boot·后端
excel1 天前
如何解决 Nuxt DevTools 中关于 unstorage 包的报错
前端
Rust研习社1 天前
使用 Axum 构建高性能异步 Web 服务
开发语言·前端·网络·后端·http·rust
C澒1 天前
AI 生码 - API2Code:接口智能匹配与 API 自动化生码全链路设计
前端·低代码·ai编程