在 Vue 3 中,computed 是一个非常重要的特性之一,它用于处理响应式依赖的数据计算。computed 可以看作是模板中逻辑的抽象,将数据处理从模板中剥离出来,使代码更加清晰、可维护。

一、Computed 的作用

  1. 响应式计算属性

    • 当 computed 依赖的响应式数据发生变化时,计算属性会自动重新计算。

  2. 缓存优化

    • computed 值会被缓存,只有当其依赖的数据发生改变时才会重新计算,避免了重复计算带来的性能损耗。

  3. 逻辑分离

    • 将复杂的逻辑封装到 computed 属性中,使得模板更简洁,同时便于测试和复用。

基础示例

        模板中的表达式虽然方便,但也只能用来做简单的操作。如果在模板中写太多逻辑,会让模板变得臃肿,难以维护。比如说,我们有这样一个包含嵌套数组的对象:

const author = reactive({
  name: 'John Doe',
  books: [
    'Vue 2 - Advanced Guide',
    'Vue 3 - Basic Guide',
    'Vue 4 - The Mystery'
  ]
})

我们想根据 author 是否已有一些书籍来展示不同的信息:

<p>Has published books:</p>
<span>{{ author.books.length > 0 ? 'Yes' : 'No' }}</span>

        这里的模板看起来有些复杂。我们必须认真看好一会儿才能明白它的计算依赖于 author.books。更重要的是,如果在模板中需要不止一次这样的计算,我们可不想将这样的代码在模板里重复好多遍。

因此我们推荐使用计算属性来描述依赖响应式状态的复杂逻辑。这是重构后的示例:

<script setup>
import { reactive, computed } from 'vue'

const author = reactive({
  name: 'John Doe',
  books: [
    'Vue 2 - Advanced Guide',
    'Vue 3 - Basic Guide',
    'Vue 4 - The Mystery'
  ]
})

// 一个计算属性 ref
const publishedBooksMessage = computed(() => {
  return author.books.length > 0 ? 'Yes' : 'No'
})
</script>

<template>
  <p>Has published books:</p>
  <span>{{ publishedBooksMessage }}</span>
</template>

二、Computed 的 API 使用方式

        在 Vue 3 的组合式 API(Composition API)中,使用 computed() 方法创建计算属性。

示例:基本使用

<template>
  <div>{{ fullName }}</div>
</template>

<script setup>
import { ref, computed } from 'vue'

const firstName = ref('John')
const lastName = ref('Doe')

// 计算属性:拼接全名
const fullName = computed(() => {
  return `${firstName.value} ${lastName.value}`
})
</script>

示例:带 getter 和 setter 的计算属性

虽然不常见,但 computed 支持设置 get 和 set:

<template>
  <div>{{ reversedName }}</div>
  <input v-model="reversedName" />
</template>

<script setup>
import { ref, computed } from 'vue'

const name = ref('Vue')

const reversedName = computed({
  get: () => {
    return name.value.split('').reverse().join('')
  },
  set: (newValue) => {
    name.value = newValue.split('').reverse().join('')
  }
})
</script>

 三、Computed 与 Class、Style 操作结合

        在 Vue 3 中,可以通过 :class 和 :style 绑定动态样式,而这些绑定可以借助 computed 实现条件判断和复杂逻辑。

示例 1::class 动态绑定

<template>
  <div :class="dynamicClass">这是一个 div</div>
</template>

<script setup>
import { ref, computed } from 'vue'

const isActive = ref(true)
const hasError = ref(false)

// 动态 class 计算
const dynamicClass = computed(() => {
  return {
    active: isActive.value,
    error: hasError.value,
    highlight: true
  }
})
</script>

<style>
.active {
  color: green;
}
.error {
  background-color: red;
}
.highlight {
  font-weight: bold;
}
</style>

示例 2::style 动态绑定

<template>
  <div :style="dynamicStyle">这是一个 div</div>
</template>

<script setup>
import { ref, computed } from 'vue'

const isRed = ref(true)
const fontSize = ref(16)

// 动态 style 计算
const dynamicStyle = computed(() => {
  return {
    color: isRed.value ? 'red' : 'blue',
    fontSize: `${fontSize.value}px`,
    padding: '10px'
  }
})
</script>

 四、总结

特性描述
响应式自动追踪依赖,当依赖变化时更新值
缓存如果依赖不变,返回上次的结果,提升性能
逻辑封装复杂逻辑集中管理,提高可读性和可维护性
支持 getter/setter更灵活地控制数据的获取和修改
与 class/style 结合简化动态样式的绑定逻辑

五、推荐使用场景

  • 需要根据多个响应式变量进行计算的场景。

  • 在模板中需要多次使用相同逻辑的地方。

  • 对于动态类名或样式绑定,尤其适合使用 computed 来管理。

更多推荐