初识 Vue 3 之 `computed` 的用法详解

1,450 阅读3分钟

初识 Vue 3 之 computed 的用法详解

在 Vue 3 中,computed 是构建响应式界面的核心工具之一,它允许我们基于已有数据动态计算出新的值,同时具备高效的缓存机制。本文将从基础概念到实际应用,逐步解析 computed 的用法,并通过丰富的 JavaScript 示例帮助你掌握这一重要特性。


一、初识 computed

1. 什么是 computed

computed 是 Vue 提供的计算属性,用于根据依赖的数据动态生成新的值。它的核心特点:

  • 缓存性:仅当依赖的数据发生变化时,才会重新计算。
  • 简洁性:无需手动管理依赖关系,Vue 会自动追踪。
  • 响应式:计算结果会随着依赖数据的变化自动更新。

2. 为什么需要 computed

假设有一个需求:根据用户的姓名和年龄生成问候语。如果直接在模板中拼接字符串,代码会重复且难以维护;而使用 computed 可以集中管理逻辑,提升代码可读性和性能。


二、基础用法:选项式 API

1. 基本语法

在 Vue 2 风格的选项式 API 中,computed 定义在 computed 属性下,每个计算属性是一个函数:

const app = Vue.createApp({
  data() {
    return {
      firstName: 'John',
      lastName: 'Doe',
      age: 30
    };
  },
  computed: {
    fullName() {
      return this.firstName + ' ' + this.lastName;
    },
    isAdult() {
      return this.age >= 18;
    }
  }
});
app.mount('#app');

2. 在模板中使用

<div id="app">
  <p>Full Name: {{ fullName }}</p>
  <p>Is Adult: {{ isAdult }}</p>
</div>

3. 缓存机制验证

修改 firstNamelastName 时,fullName 会重新计算;但修改其他无关数据(如 age)时,fullName 不会重新计算。


三、组合式 API 中的 computed

1. 基本语法

在 Vue 3 的组合式 API 中,computed 需要通过 import { computed } from 'vue' 引入:

import { ref, computed } from 'vue';

export default {
  setup() {
    const firstName = ref('John');
    const lastName = ref('Doe');
    const age = ref(30);

    // 定义计算属性
    const fullName = computed(() => firstName.value + ' ' + lastName.value);
    const isAdult = computed(() => age.value >= 18);

    return { firstName, lastName, age, fullName, isAdult };
  }
};

2. 优势对比

  • 更灵活:可以轻松与其他组合式 API(如 ref, reactive)结合。
  • this:直接操作局部变量,避免上下文混淆。

四、进阶特性

1. 依赖多个响应式数据

import { ref, computed } from 'vue';

export default {
  setup() {
    const price = ref(100);
    const quantity = ref(2);
    const discount = ref(0.1); // 10% 折扣

    // 计算总价:价格 × 数量 × (1 - 折扣)
    const total = computed(() => price.value * quantity.value * (1 - discount.value));

    return { price, quantity, discount, total };
  }
};

2. 嵌套计算属性

const app = Vue.createApp({
  data() {
    return { a: 1, b: 2, c: 3 };
  },
  computed: {
    sum() { return this.a + this.b + this.c; },
    doubleSum() { return this.sum * 2; } // 依赖 sum 的计算结果
  }
});

3. 与 watch 结合使用

import { ref, computed, watch } from 'vue';

export default {
  setup() {
    const count = ref(0);
    const doubleCount = computed(() => count.value * 2);

    // 监听 doubleCount 的变化
    watch(doubleCount, (newVal) => {
      console.log('Double Count:', newVal);
    });

    return { count, doubleCount };
  }
};

五、实际应用场景

场景 1:表单实时验证

import { ref, computed } from 'vue';

export default {
  setup() {
    const username = ref('');
    const password = ref('');

    // 验证用户名和密码是否符合规则
    const isValid = computed(() => {
      return username.value.length > 3 && password.value.length >= 6;
    });

    return { username, password, isValid };
  }
};

场景 2:动态表格过滤

import { ref, computed } from 'vue';

export default {
  setup() {
    const items = ref([
      { id: 1, name: 'Apple', category: 'Fruit' },
      { id: 2, name: 'Carrot', category: 'Vegetable' }
    ]);
    const filter = ref('');

    // 根据关键词过滤数据
    const filteredItems = computed(() => {
      return items.value.filter(item => item.name.includes(filter.value));
    });

    return { filter, filteredItems };
  }
};

六、常见问题与注意事项

1. 避免在 computed 中修改依赖数据

// 错误示例:会导致无限循环
const count = ref(0);
const doubleCount = computed(() => {
  count.value += 1; // 修改依赖数据
  return count.value * 2;
});

2. 正确处理异步操作

computed 是同步的,如果需要处理异步逻辑,应使用 watchmethods

3. 区分 computedmethods

  • computed:基于依赖缓存结果,适合频繁访问的计算。
  • methods:每次调用都会执行,适合无缓存需求的操作。

七、总结

  • 核心价值computed 通过自动化依赖追踪和缓存,大幅提升开发效率和性能。
  • 最佳实践
    • 确保计算属性是纯函数(无副作用)。
    • 优先使用组合式 API 的 computed,提升代码灵活性。
    • 避免在计算属性中修改依赖数据。

通过本文的示例和分析,相信你已掌握 computed 的基础用法和进阶技巧。在实际项目中,合理使用 computed 能让你的代码更简洁、高效且易于维护!