高端网站建设网站建设设计思路seo推广教程seo高级教程
计算属性
- 模板中的表达式虽然方便,但也只能用来做简单的操作。如果在模板中写太多逻辑,会让模板变得臃肿,难以维护。
推荐使用计算属性来描述依赖响应式状态的复杂逻辑
基础示例
不够好的示例
- 模板中使用了表达式,不够直观,必须认真看好一会儿才能明白它的计算依赖于 author.books
- 如果模板中需要不止一次这样的计算,这样的代码会在模板里重复好多遍。
- 因此我们推荐使用计算属性来描述依赖响应式状态的复杂逻辑
<template><p>Has published books:</p><span>{{ author.books.length > 0 ? 'Yes' : 'No' }}</span></template><script>
export default {name: 'MyInput',data() {return {author: {name: 'John Doe',books: ['Vue 2 - Advanced Guide','Vue 3 - Basic Guide','Vue 4 - The Mystery']}}}}</script><style lang="scss"></style>
使用计算属性
-
定义了一个计算属性 publishedBooksMessage
-
在模板中使用计算属性的方式和一般的属性一模一样。
-
更改此应用的 data 中 books 数组的值后,可以看到 publishedBooksMessage 也会随之改变。
Vue 会检测到 this.publishedBooksMessage 依赖于 this.author.books,所以当 this.author.books 改变时,任何依赖于 this.publishedBooksMessage 的绑定都将同时更新
,- 如果模板中多次使用计算属性,计算属性的方法只会执行一次,结果会被缓存下来,当计算属性所依赖的响应式属性发生变化时,才会再次执行重新计算。
<template><p>Has published books:</p><span>{{ publishedBooksMessage }}</span><p><button @click="author.books.splice(0,3)">author.books.splice(0,3)</button></p><p><button @click="author.books=[]">author.books=[]</button></p></template><script>
export default {name: 'MyInput',data() {return {author: {name: 'John Doe',books: ['Vue 2 - Advanced Guide','Vue 3 - Basic Guide','Vue 4 - The Mystery']}}},computed: {// 一个计算属性的 getterpublishedBooksMessage() {// `this` 指向当前组件实例return this.author.books.length > 0 ? 'Yes' : 'No'}}}</script><style lang="scss"></style>
计算属性缓存 vs 方法
- 在表达式中调用一个函数也会获得和计算属性相同的结果,
不同之处在于计算属性值会基于其响应式依赖被缓存
(注意是基于响应式依赖被缓存!!!),而 方法调用总是会在重渲染发生时再次执行函数-
一个计算属性仅会在其响应式依赖更新时才重新计算。这意味着只要 author.books 不改变,无论多少次访问 publishedBooksMessage 都会立即返回先前的计算结果,而不用重复执行 getter 函数
-
这也解释了为什么下面的计算属性永远不会更新,因为 Date.now() 并不是一个响应式依赖:
computed: {now() {return Date.now()} }
-
可写计算属性
计算属性默认是只读的
。当你尝试修改一个计算属性时,你会收到一个运行时警告- 只在某些特殊场景中你可能才需要用到“可写”的属性,你
可以通过同时提供 getter 和 setter 来创建
示例
- 监听input的输入事件,当input发生输入事件时,触发监听函数,将监听的值设置给计算属性,则计算属性的setter方法会被调用。
- setter方法调用中,触发了计算属性的响应式依赖发生变化,因此,又会重新渲染页面,计算属性的getter方法将被调用。
MyInput.vue
<template><custom-input/>
</template><script>import CustomInput from './CustomInput.vue';export default {name: 'MyInput',components:{CustomInput}
}</script><style lang="scss"></style>
CustomInput.vue
<template><input type="text" :value="fullName" @input="handleInput($event)">{{ fullName }}</template><script>export default {name: 'CustomInput',data() {return {firstName:'zeng',lastName: 'jian',}},methods: {handleInput(e) {console.log(e.target.value);this.fullName = e.target.value}},computed: {fullName: {get() {console.log('getter');return this.firstName + '-' + this.lastName},set(val) {console.log('setter');this.firstName = val.split('-')[0]this.lastName = val.split('-')[1]}}}
}</script><style lang="scss"></style>
最佳实践
Getter 不应有副作用
-
计算属性的 getter 应只做计算而没有任何其他的副作用
,- 这一点非常重要,请务必牢记。举例来说,
不要在 getter 中做异步请求或者更改 DOM!
一个计算属性的声明中描述的是如何根据其他值派生一个值。因此 getter 的职责应该仅为计算和返回该值。在之后的指引中我们会讨论如何使用监听器根据其他响应式状态的变更来创建副作用。
- 这一点非常重要,请务必牢记。举例来说,
-
避免直接修改计算属性值
- 从计算属性返回的值是派生状态。可以把它看作是一个“临时快照”,每当源状态发生变化时,就会创建一个新的快照。更改快照是没有意义的,因此
计算属性的返回值应该被视为只读的,并且永远不应该被更改——应该更新它所依赖的源状态以触发新的计算
。
- 从计算属性返回的值是派生状态。可以把它看作是一个“临时快照”,每当源状态发生变化时,就会创建一个新的快照。更改快照是没有意义的,因此