Appearance
计算属性
基础示例
javascript
const author = reactive({
name: 'John Doe',
books: ['Vue 2 - Advanced Guide', 'Vue 3 - Basic Guide', 'Vue 4 - The Mystery'],
})html
<p>Has published books:</p>
<span>{{ author.books.length > 0 ? 'Yes' : 'No' }}</span>当页面上的某个信息需要根据某个数据的具体内容来展示,模板表达式虽然允许我们进行一些简单的计算,但难免会使模板变得臃肿 特别是当这种现象需要多次使用时,这是就可以使用计算属性来简化模板表达式
javascript
import { computed } from 'vue'
const author = reactive({
name: 'John Doe',
books: ['Vue 2 - Advanced Guide', 'Vue 3 - Basic Guide', 'Vue 4 - The Mystery'],
})
const hasPublishedBooks = computed(() => (author.books.length > 0 ? 'Yes' : 'No'))html
<p>Has published books:</p>
<span>{{ hasPublishedBooks }}</span>上面的代码中,我们定义了一个计算属性hasPublishedBooks,它会根据author.books.length的值来决定他的值 computed() 方法期望接收一个getter函数,返回值为一个计算属性refVue的计算属性会自动追踪响应式依赖,它会检测到hasPublishedBooks依赖于author.books,当author.books发生变化时,计算属性会自动更新
计算属性缓存 vs 方法
在表达式中展示数据时,使用计算属性和方法都能获得相同的效果
html
<p>{{ calculateBooksMessage() }}</p>
// 组件中 function calculateBooksMessage() { return author.books.length > 0 ? 'Yes' : 'No' }然而不同之处在于,计算属性值会基于其依赖的响应式数据被缓存,只有在其依赖的响应式数据发生更新时才会重新计算,而使用方法来表示的话,每次调用都会执行一次代码逻辑,这也解释了,为什么下面这段代码不会更新
javascript
const now = computed(() => Date.now())可写属性
计算属性默认只读.尝试修改时会收到运行时警告.但你也可以通过同时提供getter setter 来创建可写的计算属性
<script setup>
import { ref, computed } from 'vue'
const firstName = ref('John')
const lastName = ref('Doe')
const fullName = computed({
// getter
get() {
return firstName.value + ' ' + lastName.value
},
// setter
set(newValue) {
// 注意:我们这里使用的是解构赋值语法
[firstName.value, lastName.value] = newValue.split(' ')
}
})
</script>运行 fullName.value = 'John Doe' 时,setter 会被调用而 firstName 和 lastName 会随之更新。
获取上一个值
- 仅3.4+版本支持 可以通过访问计算属性的
getter的第一个参数来获取计算属性返回的上一个值
javascript
const count = ref(2)
// 这个计算属性在 count 的值小于或等于 3 时,将返回 count 的值。
// 当 count 的值大于等于 4 时,将会返回满足我们条件的最后一个值
// 直到 count 的值再次小于或等于 3 为止。
const alwaysSmall = computed((previous) => {
if (count.value <= 3) {
return count.value
}
return previous
})javascript
<script setup>
import {ref, computed} from 'vue'
const count = ref(2)
const alwaysSmall = computed({
get(previous) {
if (count.value <= 3) {
return count.value
}
return previous
},
set(newValue) {
count.value = newValue * 2
}
})
</script>最佳实践
Getter 不应该又副作用
计算属性的getter应该只做计算而没有任何其他副作用,不要改变其他状态,不要操作DOM,不要进行异步操作等等.如果需要执行其他副作用,应该使用watch来实现
避免直接修改计算属性值
计算属性本意时返回一个派生值,每当源数据发生变化是就生成一个新的派生值.更改这个派生的值时没有意义的,这也是为什么计算属性默认是只读的