Vue3 09.计算属性
模板中的表达式虽然方便,但也只能用来做简单的操作。如果在模板中写太多逻辑,会让模板变得臃肿,难以维护。
const author = reactive({ |
Computed
如果想根据author
是否已有一些书籍来展示不同的信息:
<p>Has published books:</p> |
这里的模板,它的计算依赖于author.books
。如果在模板中需要不止一次这样的计算,不想在模板里面重复很多遍的话,推荐使用计算属性来描述依赖响应式状态的复杂逻辑。
<script setup> |
这里定义了一个计算属性publishedBooksMessage
。computed()
方法期望接收一个getter函数,返回值为一个计算属性ref。和其他一般的ref类似,可以通过publishedBooksMessage.value
访问计算结果。
计算属性ref也会在模板中自动解包,因此在模板表达式中引用时无需添加.value
。
Vue的计算属性会自动追踪响应式依赖。它会检测到publishedBooksMessage
依赖于author.books
,所以当author.books
改变时,任何依赖于publishedBooksMessage
的绑定都会同时更新。
计算属性和方法区别
如果我们使用函数也可以得到一个类似的结果:
<p>{{ calculateBooksMessage() }}</p> |
function calculateBooksMessage() { |
这和计算属性得到的结果时完全相同的。不同之处在于计算属性值会基于其响应式依赖被缓存。一个计算属性仅会在其响应式依赖更新时才会重新计算。这说明只要author.books
不改变,无论多少次访问publishedBooksMessage
都会立即返回之前的计算结果,而不用重复执行getter函数。
像这个计算属性就永远不会更新,因为Date.now()
并不是一个响应式依赖。
const now = computed(() => Date.now()) |
相比之下,方法调用总是会在重渲染发生时再次执行函数。这样的话,如果有一个非常耗性能操作,没有缓存的话会重复执行非常多次getter,但是实际上并不需要。
可写计算属性
计算属性默认是只读的,当尝试修改一个计算属性时,会收到一个运行时警告。只在某些特殊场景中需要用到“可写”的属性,可以同时提供getter和setter来创建:
<script setup> |
当给fullName
赋值时,fullName.value='Hello World'
时,setter会被调用而firstName
和lastName
会随之更新。
获取上一个值
如果需要,可以通过访问计算属性的getter的第一个参数来获取计算属性返回的上一个值:
<script setup> |
注意点
1. Getter不应该有副作用
计算属性的Getter应只做计算而没有任何其他的副作用,这一点非常重要。不要改变其他状态、在Getter中做异步请求或者更改DOM!
2. 避免直接修改计算属性值
从计算属性返回的值时派生状态,是一个”临时快照“,每当源状态发生变化时,就会创建一个新的快照。更改快照时没有意义的,因此计算属性的返回值应该被视为只读的,并且永远不应该被更改,应该更新它所依赖的源状态来触发新的计算。