计算属性的设计背景:在 Vuejs 开发时我们可以在模板中通过编写表达式的方式做一系列的逻辑处理,但这就偏离的模板的概念,还会使得模板的内容变得臃肿且难以维护,所以引入了计算属性的来对不该出现在模板中的复杂逻辑处理进行重构,使用计算属性重构后的依然保持了状态的响应式。
在类组件中,通过使用类属性的访问器方法(getter
、setter
)来描述计算属性的读写操作。在下面的代码中就是一个应用计算属性的典型场景。
基础示例
在计算属性的 getter
中应该仅做计算而不包含任何其他的副作用,应该严厉禁止在 getter
中做异步请求或改变 DOM。getter
的触发会使得数据的变化,数据的变化会驱动 DOM 的变化,这是一个正向的流程,强行对 DOM 进行修改会导致数据与 DOM 不同步,也会造成性能问题(getter
会频繁触发)。
vue
<script lang="ts">
import { Component, Vue } from 'vue-facing-decorator';
@Component
export default class App extends Vue {
firstName = '';
lastName = '';
// 计算属性(标记为 get 访问器):对 firstname 和 lastname 进行合并
get fullName() {
return this.firstName + '/' + this.lastName;
}
}
</script>
<template>
<div>
<p>firstName:<input v-model="firstName" /></p>
<p>lastName:<input v-model="lastName" /></p>
<p>fullName:{{ fullName }}</p>
</div>
</template>
<script lang="ts">
import { Component, Vue } from 'vue-facing-decorator';
@Component
export default class App extends Vue {
firstName = '';
lastName = '';
// 计算属性(标记为 get 访问器):对 firstname 和 lastname 进行合并
get fullName() {
return this.firstName + '/' + this.lastName;
}
}
</script>
<template>
<div>
<p>firstName:<input v-model="firstName" /></p>
<p>lastName:<input v-model="lastName" /></p>
<p>fullName:{{ fullName }}</p>
</div>
</template>
可写的计算属性
下面的代码是改造后的支持可写的计算属性的场景,在 fullName
发生变化后会重写对 firstName
和 lastName
进行赋值。
vue
<script lang="ts">
import { Component, Vue } from 'vue-facing-decorator';
@Component
export default class App extends Vue {
firstName = '';
lastName = '';
get fullName() {
return this.firstName + '/' + this.lastName;
}
set fullName(newValue) {
[this.firstName, this.lastName] = newValue.split('/');
}
}
</script>
<template>
<div>
<p>firstName:<input v-model="firstName" /></p>
<p>lastName:<input v-model="lastName" /></p>
<p>fullName:<input v-model="fullName" /></p>
</div>
</template>
<script lang="ts">
import { Component, Vue } from 'vue-facing-decorator';
@Component
export default class App extends Vue {
firstName = '';
lastName = '';
get fullName() {
return this.firstName + '/' + this.lastName;
}
set fullName(newValue) {
[this.firstName, this.lastName] = newValue.split('/');
}
}
</script>
<template>
<div>
<p>firstName:<input v-model="firstName" /></p>
<p>lastName:<input v-model="lastName" /></p>
<p>fullName:<input v-model="fullName" /></p>
</div>
</template>
原生访问器
在类组件中如果要使用原生的 getter
、setter
时需要用 vfd 提供得 @Vanilla
装饰器。