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. 适用场景 :所有基于现有数据计算新值的场景
相关推荐
2501_921930831 小时前
ReactNative项目OpenHarmony三方库集成实战:react-native-appearance(更推荐自带的Appearance)
javascript·react native·react.js
井川不擦2 小时前
前端安全通信方案:RSA + AES 混合加密
前端
孜孜不倦不忘初心2 小时前
Ant Design Vue 表格组件空数据统一处理 踩坑
前端·vue.js·ant design
AD_wjk2 小时前
Android13系统集成方案
前端
Joyee6912 小时前
RN 的新通信模型 JSI
前端·react native
somebody2 小时前
零经验学 react 的第6天 - 循环渲染和条件渲染
前端
青晚舟2 小时前
AI 时代前端还要学 Docker & K8s 吗?我用一次真实部署经历说清楚
前端·github
墨鱼笔记2 小时前
不使用微前端:如何实现主应用和子模块动态管理与通信实现
前端
csdn_aspnet2 小时前
查看 vite 与 vue 版本
javascript·vue.js