当前位置:  首页>> 技术小册>> TypeScript和Vue从入门到精通(二)

6.2.3 计算属性的赋值

在Vue.js框架中,计算属性(Computed Properties)是一种强大的特性,它允许组件基于它们的响应式依赖进行缓存。这意味着只有当计算属性所依赖的响应式数据发生变化时,计算属性才会重新求值。这种机制不仅优化了性能,还使得代码更加简洁和易于维护。在TypeScript与Vue结合使用时,计算属性的定义和赋值变得更加类型安全,进一步提升了开发效率和项目的可维护性。

6.2.3.1 理解计算属性的基本概念

在深入探讨计算属性的赋值之前,首先需要明确计算属性的基本概念。计算属性是基于它们的依赖进行缓存的响应式属性。Vue会自动追踪计算属性所依赖的数据,并在依赖发生变化时重新计算该属性。与在模板或方法(methods)中直接执行表达式相比,计算属性提供了更好的性能,因为它们是基于它们的响应式依赖进行缓存的。

在Vue组件中,计算属性通过computed选项定义,它是一个对象,其中每个属性都是一个计算属性。每个计算属性都可以包含一个getter函数和一个可选的setter函数。getter函数用于计算并返回计算属性的值,而setter函数则用于在尝试修改计算属性时执行特定的逻辑。

6.2.3.2 TypeScript中计算属性的定义

在TypeScript中使用Vue时,计算属性的定义需要考虑到类型安全。这意味着在计算属性的getter和setter函数中,你需要明确指定返回值的类型以及setter函数中参数的类型。Vue 3的Composition API与Vue 2的Options API在TypeScript中的使用方式略有不同,但基本概念相同。

Vue 2 Options API中的计算属性

在Vue 2的Options API中,计算属性通过组件的computed选项定义为一个对象,其中每个键是计算属性的名称,每个值是一个返回计算结果的函数(getter),或者是一个包含getter和setter的对象。

  1. <script lang="ts">
  2. import Vue from 'vue';
  3. export default Vue.extend({
  4. data() {
  5. return {
  6. firstName: 'John',
  7. lastName: 'Doe',
  8. };
  9. },
  10. computed: {
  11. // 仅getter的计算属性
  12. fullName(): string {
  13. return `${this.firstName} ${this.lastName}`;
  14. },
  15. // 包含getter和setter的计算属性
  16. reversedFullName: {
  17. get(): string {
  18. return this.fullName.split('').reverse().join('');
  19. },
  20. set(value: string) {
  21. // 这里可以编写一些逻辑来处理设置值,但通常不建议直接修改依赖数据
  22. console.log(`Attempting to set reversedFullName to: ${value}`);
  23. // 注意:实际应用中,可能需要一种更复杂的方式来处理这种情况
  24. },
  25. },
  26. },
  27. });
  28. </script>
Vue 3 Composition API中的计算属性

在Vue 3的Composition API中,计算属性通过computed函数创建,该函数来自vue包中的reactiveref的上下文。这使得计算属性更加灵活,因为它们可以独立于组件实例被定义和重用。

  1. <script lang="ts" setup>
  2. import { ref, computed } from 'vue';
  3. const firstName = ref('John');
  4. const lastName = ref('Doe');
  5. // 仅getter的计算属性
  6. const fullName = computed(() => {
  7. return `${firstName.value} ${lastName.value}`;
  8. });
  9. // 在Composition API中,通常不直接为计算属性提供setter,因为大多数计算属性是只读的
  10. // 如果需要可写的响应式数据,考虑使用ref或reactive直接管理
  11. </script>

6.2.3.3 计算属性的赋值与响应性

在计算属性的上下文中,“赋值”一词通常指的是设置计算属性的值。然而,需要注意的是,大多数计算属性是只读的,即它们没有setter函数。这意呀着你不能直接为计算属性赋值,因为它们是基于依赖的响应式数据动态计算出来的。

如果你的场景确实需要一个可写的属性,并且这个属性的值是基于其他响应式数据计算得出的,你应该考虑使用refreactive来直接管理这个属性,并在需要时更新它。然而,在这种情况下,你可能需要手动处理依赖变化时的响应性更新,这可能会比使用计算属性更复杂。

对于包含setter的计算属性,虽然可以定义它们,但应谨慎使用。setter函数允许你在尝试设置计算属性的值时执行自定义逻辑,但这通常不是推荐的做法,因为它可能会引入难以追踪的副作用和复杂性。

6.2.3.4 实战案例分析

假设我们正在开发一个购物车应用,其中需要显示购物车中商品的总价。这个总价是基于购物车中每个商品的价格和数量计算得出的。

在Vue 2的Options API中,我们可以这样定义计算属性:

  1. <script lang="ts">
  2. export default Vue.extend({
  3. data() {
  4. return {
  5. cartItems: [
  6. { id: 1, price: 10, quantity: 2 },
  7. { id: 2, price: 20, quantity: 1 },
  8. ],
  9. };
  10. },
  11. computed: {
  12. totalPrice(): number {
  13. return this.cartItems.reduce((total, item) => total + item.price * item.quantity, 0);
  14. },
  15. },
  16. });
  17. </script>

在Vue 3的Composition API中,相应的实现可能是这样的:

  1. <script lang="ts" setup>
  2. import { ref, computed } from 'vue';
  3. const cartItems = ref([
  4. { id: 1, price: 10, quantity: 2 },
  5. { id: 2, price: 20, quantity: 1 },
  6. ]);
  7. const totalPrice = computed(() => {
  8. return cartItems.value.reduce((total, item) => total + item.price * item.quantity, 0);
  9. });
  10. </script>

在这两个例子中,totalPrice都是一个只读的计算属性,它基于cartItems数组中的商品价格和数量动态计算总价。你不能直接为totalPrice赋值,因为它是基于cartItems的响应式变化自动更新的。

6.2.3.5 结论

计算属性是Vue中非常有用的特性,它们允许你基于组件的响应式数据动态计算值,并且这些计算值是基于它们的依赖进行缓存的。在TypeScript与Vue结合使用时,计算属性的定义和赋值变得更加类型安全,这有助于提升代码的可维护性和开发效率。然而,需要注意的是,大多数计算属性是只读的,并且你不应该直接为它们赋值。如果需要可写的响应式数据,请考虑使用refreactive来直接管理这些数据。


该分类下的相关小册推荐: