Vue 计算属性

Vue 计算属性

基础示例​

模板中的表达式虽然方便,但仅适用于简单操作。若在模板中写入过多逻辑,会导致模板臃肿、难以维护。例如,有一个包含嵌套数组的对象:

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>

这种写法不仅可读性差,还存在重复代码的问题(若多次使用该逻辑)。因此,推荐使用计算属性描述依赖响应式状态的复杂逻辑,重构后的示例如下:

<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>

image

核心说明

  • computed() 方法接收一个 getter 函数,返回值为计算属性 ref
  • 可通过 publishedBooksMessage.value 访问计算结果(与普通 ref 一致)。
  • 模板中会自动解包计算属性 ref,无需添加 .value
  • Vue 会自动追踪响应式依赖:当 author.books 变化时,所有依赖 publishedBooksMessage 的绑定都会同步更新。

计算属性缓存 vs 方法​

功能对比

通过函数调用也能实现与计算属性相同的结果,例如:

<!-- 模板 -->
<p>{{ calculateBooksMessage() }}</p>
// 组件中
function calculateBooksMessage() {
  return author.books.length > 0 ? 'Yes' : 'No'
}

但两者的核心区别在于缓存机制

特性 计算属性 方法
缓存机制 基于响应式依赖缓存结果 无缓存,每次调用重新执行
执行时机 仅依赖更新时重新计算 组件重渲染时必执行
性能优化 适合复杂计算/频繁访问场景 适合无需缓存的简单逻辑

关键示例

  1. 计算属性的缓存特性:
// Date.now() 非响应式依赖,因此该计算属性永远不会更新
const now = computed(() => Date.now())
  1. 缓存的意义:
    • 若有一个耗性能的计算属性(如循环巨大数组),且被多次引用,缓存可避免重复执行 getter 函数,大幅提升性能。
    • 若确定无需缓存,直接使用方法调用即可。

可写计算属性

计算属性默认只读,修改时会触发运行时警告。如需“可写”功能,可同时提供 getter 和 setter:

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

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

const fullName = computed({
  // getter:获取计算结果
  get() {
    return firstName.value + ' ' + lastName.value
  },
  // setter:修改时触发的逻辑
  set(newValue) {
    // 解构赋值拆分新值
    [firstName.value, lastName.value] = newValue.split(' ')
  }
})
</script>

使用场景

当修改计算属性时,会触发 setter 并同步更新依赖的响应式状态:

// 执行后,firstName 变为 'Jane',lastName 变为 'Smith'
fullName.value = 'Jane Smith'

获取上一个值

  • 仅支持 Vue 3.4+
  • 可通过计算属性 getter 的第一个参数,获取上一次的计算结果。

只读计算属性示例

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

const count = ref(2)

// 逻辑:count ≤ 3 时返回当前值;count ≥ 4 时返回最后一个满足条件的值(直到 count 再次 ≤ 3)
const alwaysSmall = computed((previous) => {
  if (count.value <= 3) {
    return count.value
  }
  return previous // 返回上一个值
})
</script>

可写计算属性示例

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

const count = ref(2)

const alwaysSmall = computed({
  get(previous) {
    if (count.value <= 3) {
      return count.value
    }
    return previous
  },
  set(newValue) {
    count.value = newValue * 2 // 修改时同步更新 count
  }
})
</script>
posted @ 2025-11-28 13:46  Jing61  阅读(0)  评论(0)    收藏  举报