温故知新 Vue 3: Lesson 3
Computed Properties and Watchers
Computed Properties
<div id="computed-basics">
<p>Has published books:</p>
<span>{{ author.books.length > 0 ? 'Yes' : 'No' }}</span>
</div>
In-template expressions are very convenient, but they are meant for simple operations.
template 里面的表达式是为了简单的操作而准备的.
Putting too much logic in your templates can make them bloated and hard to maintain.
template 里面放入过多的逻辑, 会使代码膨胀, 难以维护.
<div id="computed-basics">
<p>Has published books:</p>
<span>{{ publishedBooksMessage }}</span>
</div>
<script>
Vue.createApp({
data() {
return {
author: {
name: "John Doe",
books: [
"Vue 2 - Advanced Guide",
"Vue 3 - Basic Guide",
"Vue 4 - The Mystery",
],
},
};
},
computed: {
// a computed getter
publishedBooksMessage() {
// `this` points to the vm instance
return this.author.books.length > 0 ? "Yes" : "No";
},
},
}).mount("#computed-basics");
</script>
Vue is aware that vm.publishedBooksMessage depends on vm.author.books, so it will update any bindings that depend on vm.publishedBooksMessage when vm.author.books changes.
Vue 知道 computed property 依赖的 data, 当 data 变化时, computed property 会自动更新
the computed getter function has no side effects
computed getter 没有 side effects. 即不会 改变 data 或 发起异步请求.
Computed Caching vs Methods
computed properties are cached based on their reactive dependencies. A computed property will only re-evaluate when some of its reactive dependencies have changed.
computed property 会基于它们的 reactive dependency 进行 cache 缓存. 只有 reactive dependency 发生变化时, computed property 才会 re-evaluate 重新计算.
a method invocation will always run the function whenever a re-render happens.
而 method 总是会在 re-render 发生时, 重新调用.
什么时候使用 computed? 什么时候使用 method?
当你重新计算的代价比较大时, 使用 computed. 当你每次重新渲染都需要得到新的值时, 使用 method.
Imagine we have an expensive computed property list, which requires looping through a huge array and doing a lot of computations. Then we may have other computed properties that in turn depend on list. Without caching, we would be executing list’s getter many more times than necessary! In cases where you do not want caching, use a method instead.
比如你有一个 list , size 很大, 并且做了很多运算. 还有其他的 property 依赖于这个 list .如果使用 method, 每次使用都需要计算, 要消耗大量性能.
Computed Setter
// ...
computed: {
fullName: {
// getter
get() {
return this.firstName + ' ' + this.lastName
},
// setter
set(newValue) {
const names = newValue.split(' ')
this.firstName = names[0]
this.lastName = names[names.length - 1]
}
}
}
// ...
默认 computed property 是没有 side effects, 因而不能直接赋值, 但设置了 setter 之后可以.
Watchers
Vue provides a more generic way to react to data changes through the watch option.
Vue 提供了一种一般的方式, 来对 data 变化做出反应.
This is most useful when you want to perform asynchronous or expensive operations in response to changing data.
当你想针对 data 的变化, 来进行异步或花费较大的操作时, 十分有用
you can also use the imperative vm.$watch API
或者, 你也可以使用 vm.$watch api
<div id="watch-example">
<p>
Ask a yes/no question:
<input v-model="question" />
</p>
<p>{{ answer }}</p>
</div>
<script>
//...
watch: {
// whenever question changes, this function will run
question(newQuestion, oldQuestion) {
if (newQuestion.indexOf('?') > -1) {
this.getAnswer()
}
}
},
//...
// or use vm.$watch
const questionCb = (newQuestion, oldQuestion) {
if (newQuestion.indexOf('?') > -1) {
vm.getAnswer()
}
}
vm.$watch(vm.question, questionCb)
</script>
Computed vs Watched Property
it is often a better idea to use a computed property rather than an imperative watch callback
通常使用 computed property 会比使用 watch 好
//...
watch: {
firstName(val) {
this.fullName = val + ' ' + this.lastName
},
lastName(val) {
this.fullName = this.firstName + ' ' + val
}
}
//...
//...
computed: {
fullName() {
return this.firstName + ' ' + this.lastName
}
}
//...
本文使用 mdnice 排版