今天让我们来讨论一下计算属性.

到目前为止,你已经了解了 Vue 如何处理它自己的本地状态,即我们放在 data 中的状态,以及组件如何处理它的 prop 属性 - 即父组件传递下来的属性。

然而,在 Vue 中还有一种计算属性类型的属性。让我们今天来看看这些内容。

今天我们将使用一个全新的样例,以便于我们可以构建一个清晰的例子。以下是代码。

<html> <head> <title>Vue 101</title> </head> <body> <div id="app"> <age-calculator></age-calculator> </div> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script> Vue.component('age-calculator', { template: ` <p> NAME has been kicking butt for X days! </p> ` }); const app = new Vue({ el: '#app' }); </script> </body> </html>

我已经为 age-calculator 组件做好脚手架了,不过现在它只能输出一个带有 X 的 <p> 标签,随后我们还会在组件内做一些计算。而且我还向 div#app 添加了相应的组件标签 <age-calculator>

如果你需要复习下基础组件,请看下这个系列的第五部分 为 Vue.js 新手准备的实战入门教程 – 第五章,也可以直接看官方文档 the official docs

当简单属性不能满足需求的时候

在开始写代码之前,先聊聊我们要做什么事情。

我想创建一个组件,这个组件可以在我传递某个人的年龄的时候展示他们到底吃了多少天煎饼果子?。如果你说你不喜欢吃煎饼,拜拜祝好。

先处理下我们已经知道如何处理的部分,首先需要一个包含了人名和年龄的数组方便我们循环并且输出一组组件。添加的对应数据 data 如下。

const app = new Vue({ el: '#app', data: { people: [ { name: 'Mario', age: 38 }, { name: 'Luigi', age: 38 }, { name: 'Samus', age: 31 }, { name: 'Link', age: 20 }, { name: 'Marina', age: 32 }, //Add yourself here :) ] } });

接下来,配置下 v-loop 循环输出给每一个 age-calculator 组件。

<div id="app"> <age-calculator v-for="person in people" :key="person.name"></age-calculator> </div>

真棒,接下来让 age-calculator 组件接受 person 属性,记着要用 prop 组件属性。所以现在先给这个组件加一个新的 prop

Vue.component('age-calculator', { props: { person: { type: Object, required: true } }, template: ` <p> {{ person.name }} has been kicking butt for X days! </p> ` });

补充! 在你学习去声明一个组件可以接收的属性之前,你创建了一个字符串矩阵 props: ['person'],这在大多数时间是可以的。但是如果我们想要更多的控制会发生什么呢?

你也可以像这个例子,设置 props 等于一个 object。在这个对象中,我们可以为每一个我们想声明的属性创建一个属性。

在属性声明中,在本例中是 person,我们可以设置一些配置值。

type 来声明我们传递的数据的哪个 (duh) 类型,例如 ObjectArrayStringNumber.

required 是一个布尔值,它允许我们将该属性标记为组件工作所需的属性。

你还可以设置一个默认值,但是我们在这里不会使用它。

接下来,看一下这个模版。我们正在将一个人的名字输出到 <p> 标签中。

在浏览器中运行这个之前还有一件事。你能告诉我我们少了什么吗?

我们仍然需要传递实际的 personage-calculator 组件中。

进入渲染的循环中传入我们的变量。

<age-calculator v-for="person in people" :person="person" :key="person.name"></age-calculator>

继续并在浏览器中运行它来检查一切是否正常。初级阶段!

请注意在我们继续之前,如果您想知道将 “道具” 设置为 required 会为您带来什么,请尝试删除我们在将 person 传递到组件时所做的最后一点,并在控制台部分查看您的开发工具。

很方便,不是吗??

真正的计算属性

好了,设置和回顾已经够多了。

我们的组件中还有一个功能需要处理,我们想要计算每个人活着的天数。

诚然,这不是一个非常难得计算,
当然,这不是一个很难计算的问题,我们只需要用 365 乘以年数 (这里我们不打算使用 JS 日期)。实际上,我们可以直接把这个直接放到模板中。

template: ` <p> {{ person.name }} has been kicking butt for {{ person.age * 365 }} days! </p> `

这在某种程度上是可行的。但是当你需要更多的逻辑时会发生什么呢?一个更难的计算,一些 ifs/ands/ors/whens/beer ? 这样就会遇到真正的问题,因为不能在模板中放入那么多逻辑,否则很快就会变得难以管理。

这就是计算属性的闪光点。计算属性在函数的末尾,它会执行一点代码,并返回一个值。这个值现在被视为一个属性,这就意味着我们可以在模版中直接使用它。

让我们看看如何设置它。首先,让我们将计算后的包装器添加到组件中。

Vue.component('age-calculator', { props: { person: { type: Object, required: true } }, template: ` <p> {{ person.name }} has been kicking butt for {{ person.age * 365 }} days! </p> `, computed: { // 计算属性放这里 } });

目前为止都很好,实际上这个结构体和我们在方法中使用的完全一样,你还记得么?(如果你认为有一种方法也可以解决我们的问题,那你就在正确的轨道上 - 我们稍后将会讨论这个问题。)

让我们来创建一个新的计算属性,称之为 daysAlive,它需要是一个函数,也需要返回一些东西。

computed: { daysAlive() { //记住,计算属性在一个函数的末尾 return this.person.age * 365 } }

请注意,就像在方法中,我们需要通过 this 来访问 person 属性,只有在模板中我们才能直接使用它!除此之外,没有什么特别的事情发生。

现在让我们在模板中使用这个新的 daysAlive 属性。

template: ` <p> {{ person.name }} has been kicking butt for {{ daysAlive }} days! </p> `,

注意我们正在输出 daysAlive – 属性 – 的值,(aha moment here). Vue 将计算的属性也当作属性 - 因此我们可以在这里使用它,就像 props 属性或 data 属性一样。

事实上,Vue 使得例如你如果需要在一个方法中使用这个属性,你必须通过 this.daysAlive 来访问它。很整洁对吧?事实上它变成了一个属性 ?

耶✌️,在浏览器中运行它,尽情享受你的魅力吧。

# 方法 vs 计算属性

你可能已经注意到方法和计算属性之间的很多相似性,我的意思是,他们都是在代码层本质上是一样的。然而,为了充分利用它们,您需要了解其中的一个核心区别。

计算属性有缓存.

这意味着,用最简单的方式来解释,在幕后 Vue 将 “阅读” 你的代码,并寻找反应性依赖 - 所以数据道具和属性道具。它将监视这些属性,当它们发生变化时,Vue 将重新计算计算出的属性的值。如果它们没有改变,它就会使用缓存 / 存储的值。

另一方面,方法每次都会运行 - 没有缓存、没有代码读取、没有魔术。它们只是普通的旧函数。

这有什么重要的?何时调用这些函数?

每次您的组件 / 应用程序重新呈现时 (因此每次组件的数据更改,或者它的父组件的数据更改),Vue 都会判断该数据是否绑定到 Computed 属性,如果不是 - 它不会再次调用此函数。但是,对于常规方法,它们将在每次重新运行!

对于这个示例,我们对这几个对象进行非常简单的计算,坦率地说,这并不重要。但是,当您开始在一千个组件之上执行一些严肃的代码提升时,您将需要利用此缓存,否则您的应用程序将在每个呈现周期中受到影响。

如果你想阅读更多内容,下面是关于计算属性的官网链接.

这是今天的完整代码.

<html> <head> <title>Vue 101</title> </head> <body> <div id="app"> <age-calculator v-for="person in people" :person="person" :key="person.name"></age-calculator> </div> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script> Vue.component('age-calculator', { props: { person: { type: Object, required: true } }, template: ` <p> {{ person.name }} has been kicking butt for {{ daysAlive }} days! </p> `, computed: { daysAlive() { return this.person.age * 365 } } }); const app = new Vue({ el: '#app', data: { people: [ { name: 'Mario', age: 38 }, { name: 'Luigi', age: 38 }, { name: 'Samus', age: 31 }, { name: 'Link', age: 20 } ] } }); </script> </body> </html>