Skip to content
On this page

什么是计算属性?

计算属性(computed)是一类特殊的属性,它的值由其他数据计算得出,而且 Vue 会缓存结果。 简单说:有依赖别人才能算出来的值,就放 computed 里

一个例子看懂

vue
<template>
  <p>原始数组:{{ numbers }}</p>
  <p>偶数数组:{{ evenNumbers }}</p>
</template>
<script>
export default {
  data() {
    return {
      numbers: [1, 2, 3, 4, 5, 6]
    }
  },
  computed: {
    evenNumbers() {
      return this.numbers.filter(n => n % 2 === 0)
    }
  }
}
</script>

输出:

原始数组:[1, 2, 3, 4, 5, 6]
偶数数组:[2, 4, 6]

evenNumbers 不是存死的数据,而是每次根据 numbers 自动算出来的。只要 numbers 不变,evenNumbers 就用缓存的结果,不会重新算。

计算属性 vs 方法 — 关键区别

两种写法都能实现同样的功能,但行为完全不同:

vue
<template>
  <!-- 方法:每次访问都会重新执行 -->
  <p>{{ getEvenNumbers() }}</p>
  <p>{{ getEvenNumbers() }}</p>
  <p>{{ getEvenNumbers() }}</p>
  <!-- 计算属性:第一次算出后缓存,后面直接用 -->
  <p>{{ evenNumbers }}</p>
  <p>{{ evenNumbers }}</p>
  <p>{{ evenNumbers }}</p>
</template>
<script>
export default {
  data() { return { numbers: [1, 2, 3, 4, 5, 6] } },
  computed: {
    evenNumbers() {
      console.log('computed 被调用了')     // 只打印 1 次
      return this.numbers.filter(n => n % 2 === 0)
    }
  },
  methods: {
    getEvenNumbers() {
      console.log('method 被调用了')       // 打印 3 次
      return this.numbers.filter(n => n % 2 === 0)
    }
  }
}
</script>
computedmethods
缓存有(依赖不变就复用上次结果)无(每次重新计算)
调用方式像属性一样,不带括号:{{ evenNumbers }}像函数一样,带括号:{{ getEvenNumbers() }}
适用场景需要根据数据计算的展示值需要执行的动作(如事件处理)
何时用读数据时做操作时
💡 Tip:记住
computed 就像 Excel 里的公式:=SUM(A1:A10)。只要 A1:A10 的值没变,结果就不会重新算。

计算属性的 getter 和 setter

计算属性默认是"只读"的(getter)。但你也可以让它可写(setter):

vue
<template>
  <p>{{ fullName }}</p>
  <button @click="changeFullName">改名字</button>
</template>
<script>
export default {
  data() {
    return {
      firstName: '',
      lastName: ''
    }
  },
  computed: {
    fullName: {
      get() {                               // 读取时调用
        return this.firstName + this.lastName
      },
      set(newValue) {                       // 设置时调用
        this.firstName = newValue[0]
        this.lastName = newValue.slice(1)
      }
    }
  },
  methods: {
    changeFullName() {
      this.fullName = '李四'     // 触发 setter
    }
  }
}
</script>

不过 getter+setter 的计算属性用得比较少,大部分场景下只读就够了。

什么时候用 computed?

凡是符合"这个值由其他值决定"的逻辑,都应该用 computed:

  • 过滤列表(如搜索功能)
  • 格式化显示(如价格显示为 ¥ 符号)
  • 判断状态(如购物车是否为空)
  • 拼接字符串(如全名 = 姓 + 名)

新手常见问题

Q:computed 里能写异步代码吗? A:不行。computed 是同步的,必须立即返回值。如果需要异步操作,用 watchmethodsQ:computed 里能修改 data 吗? A:不能!computed 是"只读"的,在里面修改 data 会造成无限循环。改数据去 methods。 下一步: 💡 Tip:Composition API 写法(Vue 3)

vue
<script setup>
import { ref, computed } from 'vue'
const numbers = ref([1, 2, 3, 4, 5, 6])
const evenNumbers = computed(() => numbers.value.filter(n => n % 2 === 0))
</script>

详见: