深入浅出 Vue 计算属性 ( computed ) 的使用与优化

前言

Vue 的计算属性(computed)是 Vue.js 中非常重要的一个概念。它允许你在 Vue 组件中定义一些计算逻辑,这些逻辑会依赖于 Vue 的响应式数据,并且具有缓存机制,只有在依赖数据发生改变时才会重新计算,从而提高了性能。

计算属性的主要作用包括:

  • 数据转换
  • 数据过滤
  • 响应式依赖
  • 缓存机制
  • 简化模板

在本篇文章中,我们将详细探寻如何利用计算属性优化 Vue 组件的数据处理和渲染逻辑,深入了解 Vue 计算属性的精髓。

一. 认识计算属性

1. 什么是计算属性

Vue.js 中的计算属性(computed properties)是 Vue 实例中非常重要的一个特性。它们用于对 Vue 实例的数据进行动态计算,且具有缓存机制,只有在相关依赖发生改变时才会重新计算。这种特性使得计算属性非常适合用于处理模板中的逻辑。

2. 计算属性的定义

计算属性是在 Vue 实例的computed选项中定义的,可以是一个函数或具有getset方法的对象。函数形式的计算属性会在调用时被执行,而对象形式的计算属性则可以提供自定义的getset方法。

javascript 复制代码
computed: {
  // 函数形式的计算属性
  reversedMessage: function () {
    return this.message.split('').reverse().join('');
  },
  // 对象形式的计算属性
  fullName: {
    get: function () {
      return this.firstName + ' ' + this.lastName;
    },
    set: function (newValue) {
      var names = newValue.split(' ');
      this.firstName = names[0];
      this.lastName = names[names.length - 1];
    }
  }
}

3. 计算属性的依赖

计算属性可以依赖于 Vue 实例的响应式数据。当依赖数据发生改变时,相关的计算属性会重新计算。

javascript 复制代码
data: {
  message: 'Hello'
},
computed: {
  reversedMessage: function () {
    return this.message.split('').reverse().join('');
  }
}

reversedMessage计算属性依赖于message数据,当message发生变化时,reversedMessage会自动更新。

4. 计算属性的缓存

计算属性默认具有缓存机制。只有在相关依赖发生变化时,计算属性才会重新计算。多次访问计算属性时,Vue 会返回之前计算的结果,而不会重新执行计算函数,从而提高性能。

javascript 复制代码
computed: {
  reversedMessage: function () {
    return this.message.split('').reverse().join('');
  }
}

在上面的代码中,reversedMessage会在第一次访问时计算并缓存结果,之后的访问会直接返回缓存的值,除非message发生变化。

通过这些基本概念,计算属性可以帮助你更清晰、高效地处理 Vue 实例中的数据,从而简化模板逻辑,提高代码可读性和可维护性。

二. Getter 和 Setter

Getter 方法和 Setter 方法是计算属性中非常有用的功能,让我们详细了解一下它们的功能:

1. Getter 方法

计算属性的 Getter 方法用于计算并返回一个值。它类似于一个数据属性,但其值是通过计算得出的。Getter 方法在访问计算属性时被调用。

例如,在以下示例中,我们定义了一个计算属性fullName,它通过组合firstNamelastName来生成完整的姓名:

javascript 复制代码
new Vue({
  data: {
    firstName: "John",
    lastName: "Doe",
  },
  computed: {
    fullName: {
      get: function () {
        return this.firstName + " " + this.lastName;
      },
    },
  },
});

当你通过this.fullName访问fullName时,Getter 方法会被调用,并返回完整的姓名。

2. Setter 方法

计算属性的 Setter 方法用于监视计算属性被赋值时的变化,并在赋值时执行一些自定义的操作。它允许我们对计算属性进行更精细的控制。

在以下示例中,我们对fullName计算属性添加了一个 Setter 方法,用于解析新值并更新firstNamelastName

javascript 复制代码
new Vue({
  data: {
    firstName: "John",
    lastName: "Doe",
  },
  computed: {
    fullName: {
      get: function () {
        return this.firstName + " " + this.lastName;
      },
      set: function (newValue) {
        var names = newValue.split(" ");
        this.firstName = names[0];
        this.lastName = names[names.length - 1];
      },
    },
  },
});

当你尝试为fullName赋值时,Setter 方法会被调用,它会解析新值并相应地更新firstNamelastName

使用 Getter 和 Setter 方法,你可以更灵活地处理计算属性,并根据需要执行自定义操作。这使得计算属性成为 Vue.js 中处理动态数据的强大工具。

三. 计算属性的性能优化

在开发中我们会经常的使用到计算属性,为了确保性能,有时需要注意一些优化技巧。以下是一些计算属性的性能优化方法:

1. 合理利用懒计算 - lazy

计算属性的lazy选项可以用来延迟计算属性的求值。默认情况下,计算属性是在获取时立即求值的,但通过设置lazytrue,可以将计算属性的求值延迟到首次访问该属性时才进行计算。这个选项可以提升初始化时的性能。

lazy选项设置为true时,计算属性不会在组件初始化时立即计算。相反,在首次访问计算属性时,它会调用定义的计算函数并将结果缓存起来,以供后续的访问。

延迟计算属性的使用场景包括:

  1. 计算代价较高的属性: 如果计算属性的计算逻辑很复杂或需要耗费大量的计算资源,那么可以将其设置为延迟计算属性。这样,在组件初始化时不会执行这些代价较高的计算,只有在需要访问该属性时才会进行计算,避免不必要的性能损耗。

  2. 依赖其他计算属性的计算属性: 如果有一个计算属性依赖了其他计算属性,而这些依赖的计算属性是在首次访问时才进行计算的,那么可以将这个计算属性设置为延迟计算属性。这样,在首次访问该计算属性时,它会自动等待依赖计算属性的值可用后再进行计算。

要设置计算属性的lazy选项,需要在计算属性中使用对象语法,并将lazy设置为true

javascript 复制代码
computed: {
  lazyComputed: {
    get() {
      // 延迟计算的逻辑
    },
    // ...
    lazy: true
  }
}

需要注意的是,lazy选项只对 Vue2 有效,Vue3 中已移除该选项。在大多数情况下,默认的立即计算行为是足够的,只有在特定性能优化的场景中,才需要考虑使用延迟计算属性。

通过合理地使用lazy选项,可以避免不必要的计算,提高应用程序的性能。但也要注意,过度使用延迟计算属性可能会导致代码变得复杂,因此应根据实际需求进行选择和权衡。

2. 合理设置缓存行为 - cache

计算属性的cache选项用于控制计算属性的缓存行为。默认情况下,计算属性是具有缓存的,即在计算属性的依赖项不发生变化时,多次访问该计算属性将返回缓存的结果,而不会重新计算。这样可以避免不必要的计算,提高性能。

通过设置cache选项为false,可以禁用计算属性的缓存行为,这意味着每次访问该计算属性时都会重新计算,无论其依赖项是否发生变化。

禁用计算属性缓存的使用场景包括:

  1. 计算属性的值可能频繁变更: 如果计算属性的值可能频繁地发生变化,即使其依赖项没有变化,你可能需要禁用缓存。这样可以确保每次访问计算属性时都能获取到最新的计算结果。

  2. 计算属性的值依赖于外部实例状态: 如果计算属性的值依赖于外部实例状态(例如全局状态管理器或其他组件的状态),那么在这些状态发生变化时,你可能需要禁用缓存。这样可以确保计算属性能响应外部状态的变化。

要禁用计算属性的缓存,需要在计算属性中使用对象语法,并将cache选项设置为false

javascript 复制代码
computed: {
  uncachedComputed: {
    get() {
      // 计算逻辑
    },
    // ...
    cache: false
  }
}

需要注意的是,禁用计算属性的缓存行为可能会导致不必要的性能开销,特别是在计算逻辑复杂或计算频率较高的情况下。因此,只在必要时禁用缓存,并确保评估其性能影响。

在Vue3中,计算属性的缓存行为有了一些改变,默认情况下,计算属性不再具有缓存。如果需要保留缓存行为,可以将cache选项设置为true

通过合理地使用和管理计算属性的缓存,可以提高应用程序的性能和响应性。但也要注意,在某些特定情况下,禁用缓存或开启缓存可能更适合,需要根据实际需求进行选择和权衡。

3. 避免过度计算

尽量避免在计算属性中进行过于复杂或耗时的计算,以减轻性能负担。如果需要复杂计算,考虑将其分解为更小的计算属性或使用方法。

如果计算属性中的依赖项较多或算逻辑较复杂,可能会影响性能。在这种情况下,可以考虑使用计算属性的getter和setter方法进行优化,或者使用watch来监听多个数据的变化。

四. 实际项目中的应用

在实际的项目开发中,我们有很多的应用场景需要用到计算属性,比如:

  • 数据过滤
  • 表单验证
  • 数据计算结果
  • 数据格式化
  • ...

等等,应用场景很多,在这里不多做赘述。以下面一个计算价格的场景为例,我们来看一下实际场景下是如何使用的。

例如:当需要计算商品的总价时,可以使用计算属性来实现,下面我们详细说明计算属性的应用:

html 复制代码
<!DOCTYPE html>
<html>
  <head>
    <title>商品总价计算</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.14/vue.js"></script>
  </head>
  <body>
    <div id="app">
      <h2>商品列表</h2>
      <ul>
        <li v-for="product in products" :key="product.id">
          {{ product.name }} - ¥{{ product.price }}
        </li>
      </ul>
      <h2>商品总价:¥{{ totalPrice }}</h2>
    </div>

    <script>
      new Vue({
        el: "#app",
        data: {
          products: [
            { id: 1, name: "手机", price: 2999 },
            { id: 2, name: "平板", price: 1999 },
            { id: 3, name: "耳机", price: 399 },
            { id: 4, name: "电视", price: 4999 },
            { id: 5, name: "笔记本", price: 5999 },
          ],
        },
        computed: {
          totalPrice: function () {
            return this.products.reduce(function (total, product) {
              return total + product.price;
            }, 0);
          },
        },
      });
    </script>
  </body>
</html>

在上面的代码中,我们定义了一个 Vue 实例,并使用data选项定义了一个products数组,其中包含了一些商品信息,包括商品的 ID、名称和价格。

接着,在computed选项中定义了一个名为totalPrice的计算属性。这个计算属性使用reduce方法对products数组中的价格进行累加,从而得到商品的总价。最后,在模板中使用插值语法{{ totalPrice }}将计算结果显示出来。

运行上面的代码,你将看到页面上列出了商品列表,并实时计算并显示了商品的总价。如下图所示:

通过上面的示例,我们可以看到计算属性的应用方式。它能够轻松地在 Vue 实例的响应式数据上进行复杂的计算,而且只有在相关依赖发生变化时才会重新计算。同时提高了代码的可读性、可维护性和性能。

五. 最佳实践

下面是总结的一些 Vue 计算属性的最佳实践,它们可以帮助你更好地应用和管理计算属性:

  1. 保持计算属性简洁: 计算属性应该保简洁,只包含必要的逻辑。避免在计算属性中执行复杂的计算或涉及过多的业务逻辑。如果需要复杂的逻辑,可以考虑使用方法。

  2. 避免计算属性中的副作用: 计算属性应该是纯的,不应该有副作用。副作用包括修改数据、触发异步操作、调用接口等。如果需要有副作用的操作,应该放在生命周期钩子函数或观察者中。

  3. 合理使用计算属性和方法: 计算属性适合处理依赖关系和复杂的数据转换。方法适用于执行具有副作用的操作或根据需要传递参数。根据需求合理使用计算属性和方法,可以使代码更加清晰和易读。

  4. 注重性能优化: 参考文章中的第三部分 "计算属性的性能优化"

通过合理使用和管理计算属性,你可以优化应用程序的性能,更好地处理数据逻辑和依赖关系。

总结

在Vue中,计算属性是一个非常重要的特性,它允许我们在模板中使用简洁而优雅的方式来处理数据的计算和变换。通过计算属性,我们可以将复杂的逻辑封装起来,并在需要时进行复用。

通过这篇文章,我们了解到,除了缓存,Vue 还提供了lazy选项和cache选项来进一步控制计算属性的行为。通过使用lazy选项,我们可以延迟计算属性的求值,只有在首次访问该属性时才进行计算。而通过使用cache选项,我们可以禁用计算属性的缓存,每次访问都会重新计算。

综上所述,计算属性是 Vue 提供的一个非常强大和灵活的特性,它可以帮助我们简化数据处理的逻辑,并提高应用程序的性能。合理地使用计算属性,可以使我们的代码更加清晰、易于维护,并提供更好的用户体验。

相关推荐
程序媛小果6 分钟前
基于java+SpringBoot+Vue的桂林旅游景点导游平台设计与实现
java·vue.js·spring boot
喵叔哟25 分钟前
重构代码之取消临时字段
java·前端·重构
还是大剑师兰特1 小时前
D3的竞品有哪些,D3的优势,D3和echarts的对比
前端·javascript·echarts
王解1 小时前
【深度解析】CSS工程化全攻略(1)
前端·css
一只小白菜~1 小时前
web浏览器环境下使用window.open()打开PDF文件不是预览,而是下载文件?
前端·javascript·pdf·windowopen预览pdf
方才coding1 小时前
1小时构建Vue3知识体系之vue的生命周期函数
前端·javascript·vue.js
man20171 小时前
【2024最新】基于springboot+vue的闲一品交易平台lw+ppt
vue.js·spring boot·后端
阿征学IT1 小时前
vue过滤器初步使用
前端·javascript·vue.js
王哲晓1 小时前
第四十五章 Vue之Vuex模块化创建(module)
前端·javascript·vue.js
丶21361 小时前
【WEB】深入理解 CORS(跨域资源共享):原理、配置与常见问题
前端·架构·web