计算属性的概念:
Vue.js 中的计算属性是一种用于派生数据的属性。计算属性依赖于已有的响应式数据,并在数据发生变化时自动更新。计算属性与普通的数据属性不同,它是通过定义一个函数来返回计算结果的,而不是直接存储一个值。每当计算属性所依赖的数据发生变化时,该计算属性都会重新计算。
下面通过两个示例来进一步了解computed!
示例一
下面是一个示例,演示了如何使用计算属性计算一个购物车中商品总价:
<template>
<div>
<ul>
<li v-for="product in products" :key="product.id">
{{ product.name }} - {{ product.price }}
</li>
</ul>
<p>商品总价:{{ totalPrice }}</p>
</div>
</template>
<script>
export default {
data() {
return {
products: [
{ id: 1, name: '商品1', price: 100 },
{ id: 2, name: '商品2', price: 200 },
{ id: 3, name: '商品3', price: 300 },
],
};
},
computed: {
totalPrice() {
return this.products.reduce((total, product) => total + product.price, 0);
},
},
};
</script>
在上述代码中,我们创建了一个包含多个商品的数组products,每个商品对象包含id、name和price属性。通过计算属性totalPrice,我们使用reduce()函数对商品数组进行累加,计算出商品的总价。
在模板中,我们通过插值语法{{ totalPrice }}将计算属性的值显示在页面上。当products数组发生变化时,计算属性totalPrice会自动重新计算,并更新显示的总价。
通过使用计算属性,我们可以方便地派生出需要的数据,而不需要手动去管理和更新它们。
示例二
new Vue({
el: '#app',
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[1];
}
}
}
})
在这个示例中,fullName 是一个计算属性,它由 firstName 和 lastName 计算得出。在 get 函数中,我们通过 this.firstName 和 this.lastName 访问了 Vue 实例的数据。在 set 函数中,我们将字符串按照空格分割成两个部分,并更新 firstName 和 lastName 的值。
除了在计算属性中使用 Vue 实例的数据和方法,我们还可以定义自己的变量或数据,并在计算属性中使用它们。这些属性可以是局部变量或外部定义的变量,具体取决于计算属性的实现方式。
计算属性的优点和缺点:
优点:
1.响应式:计算属性会自动响应数据的变化,当所依赖的数据发生改变时,计算属性会重新计算,并更新相关的组件。这使得开发者可以轻松地创建具有响应性的界面。
2.缓存机制:计算属性具有缓存机制,只有当它所依赖的数据发生变化时,才会重新计算。如果多个组件都依赖于同一个计算属性,且其依赖数据没有改变,计算属性的值会被缓存,提高了计算性能。
3.维护性:通过计算属性,我们可以将复杂的逻辑封装在一个函数中,使代码更加清晰、可读性更强。它们提供了一种组织和管理派生数据的方式,使得代码更易维护。
缺点:
1.计算开销:计算属性是基于已有数据进行计算的,一些复杂的计算逻辑可能会占用较多的计算资源。当依赖数据量较大或计算逻辑复杂时,计算属性的性能可能会受到影响。
2.不可变性:计算属性是只读的,它们不能直接修改原始数据。计算属性依赖于其他数据进行计算,但无法直接修改这些数据。如果需要修改数据,则需要使用其他方法,如方法或监听器。
综上所述,Vue.js计算属性在开发响应式界面时非常有用,能够提供方便的派生数据和缓存机制。但当遇到复杂的计算逻辑或大量数据时,需要注意计算开销和性能问题。
使用computed的场景:
用于处理复杂的逻辑运算;
一个数据受一个或多个数据影响;
用来处理watch和methods无法处理的,或处理起来不方便的情况。
处理模板中的复杂表达式、购物车里面的商品数量和总金额之间的变化关系等等
使用computed还需要注意的几个点:
1.初始化显示或者相关的 data、props 等属性数据发生变化的时候调用;
2.计算属性不在 data 中,它是基于data 或 props 中的数据通过计算得到的一个新值,这个新值根据已知值的变化而变化;
3.在 computed 属性对象中定义计算属性的方法,和取data对象里的数据属性一样,以属性访问的形式调用;
4.如果 computed 属性值是函数,那么默认会走 get 方法,必须要有一个返回值,函数的返回值就是属性的属性值;
5.computed 属性值默认会缓存计算结果,在重复的调用中,只要依赖数据不变,直接取缓存中的计算结果,只有依赖型数据发生改变,computed 才会重新计算;
6.在computed中的,属性都有一个 get 和一个 set 方法,当数据变化时,调用 set 方法。
上面说到了缓存,那么computed是怎么实现的缓存?
在 Vue.js 中,计算属性的缓存是通过内部的依赖追踪和缓存机制实现的。当计算属性被访问时,Vue.js
会将其标记为响应式依赖,并缓存其返回值。只有当计算属性所依赖的响应式数据发生变化时,计算属性才会重新计算,并更新缓存的值。
具体而言,计算属性的缓存实现过程如下:
- 当模板中的数据绑定或组件方法中调用计算属性时,Vue.js 会创建一个依赖关系,将计算属性与所依赖的响应式数据进行关联。
- 在计算属性的 getter 函数中,Vue.js 会检查该计算属性是否已经有缓存的值。如果有,直接返回缓存值,不再重新计算。
- 如果计算属性没有缓存值,则执行计算属性的 getter 函数,并缓存计算结果。
- 在执行计算属性 getter 函数期间,当访问其他响应式数据时,Vue.js 会将这些数据添加到依赖关系中,并建立响应式依赖链。
- 当所依赖的响应式数据发生变化时,Vue.js 会通知计算属性的依赖关系,标记计算属性为“脏”(dirty)。这意味着计算属性的值需要重新计算。
- 当再次访问计算属性时,如果计算属性被标记为“脏”,Vue.js 会重新执行计算属性的 getter 函数,并缓存计算结果。
通过这个依赖追踪和缓存机制,Vue.js 能够在数据变化时智能地更新和计算计算属性的值,避免不必要的重复计算,提高性能。
new Vue({
el: '#app',
data: {
count: 0,
message: 'Hello'
},
computed: {
doubleCount: {
get: function () {
console.log('get called');
return this.count * 2;
},
set: function (newValue) {
console.log('set called');
this.count = newValue / 2;
}
}
}
})
在这个例子中,doubleCount 是一个计算属性,它依赖于 count 数据属性。在 get 函数中,我们打印了 “get called”,然后返回 count 的两倍。在 set 函数中,我们打印了 “set called”,然后将 count 的值设置为传入参数的一半。当我们第一次获取 doubleCount 属性时,由于 count 还没有变化,计算属性会使用缓存中的属性值,不会调用 get 函数,所以不会打印 “get called”。如果我们改变 count 的值,计算属性会重新计算 doubleCount,并调用 set 函数,打印 “set called”。如果我们再次获取 doubleCount 属性,计算属性会使用缓存中的属性值,不会再次调用 get 函数,所以不会再次打印 “get called”。
这个例子展示了计算属性的缓存机制。只有在依赖的数据属性发生变化时,计算属性才会重新计算,否则会使用缓存中的属性值。
注意:计算属性的缓存只针对计算属性本身而言。如果计算属性所依赖的响应式数据发生变化,但计算属性的逻辑并没有使用这些数据进行计算,那么计算属性的值将不会更新。这种情况下,可以使用watch来监听数据的变化并执行相应的操作。
如有需要补充的欢迎评论区留言!