前文
这节课我们了解计算属性与监听器
收集依赖
之前我们已经介绍过依赖收集
这节课我们继续重复一下
vue的模板库可以看做是一个watcher对象,而每一个响应式的数据是一个dep依赖对象
当我们模板在被vue处理后
会变成一个js格式的函数,我们通常叫做render函数
在render函数内会返回一个描述我们template模板的一个对象
在制作对象的时候相应会访问数据
访问数据的时候因为我们通过object.defineproperty进行了劫持
所以这时候dep对象监听到了watch对象的访问,就会收集依赖
一旦再次发生改变则进行刷新模板的更新操作
那计算属性的意义是什么呢?
计算属性也是一个vue实例,我们传入了一个计算函数,这时候如果访问了响应式数据的对象
dep对象会收集计算属性的依赖,我们计算属性在这个过程中得出到了一个结果
得到结果后,如果在dep没有改变的情况下,也就是说没有触发计算属性更新的情况下
则永远返回之前计算的结果,通过这种操作来节省计算资源和时间。
例子
<div id="computed-basics">
<p>Has published books:</p>
<span>{{ publishedBooksMessage }}</span>
</div>
Vue.createApp({
data() {
return {
author: {
name: 'John Doe',
books: [
'Vue 2 - Advanced Guide',
'Vue 3 - Basic Guide',
'Vue 4 - The Mystery'
]
}
}
},
computed: {
// 计算属性的 getter
publishedBooksMessage() {
// `this` 指向 vm 实例
return this.author.books.length > 0 ? 'Yes' : 'No'
}
}
}).mount('#computed-basics')
而如果我们在模板使用普通函数,并不使用计算属性,这时候普通函数是不具有依赖收集能力的
也就是说一旦重复刷新,即使我们的数据没有改变,依然要重复一次计算操作,消耗大量的资源。
计算属性也可以使用set
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]
}
}
}
跟object.defineproperty基本一致,这里就暂且不表了。
侦听器
侦听器其实也是非常简单,计算属性是根据我们使用的对象计算出一个返回值
而侦听属性则是访问响应对象,当触发了对象的依赖收集之后,如果对象发生改变,通知侦听器
侦听器就会调用我们的用户函数来回调,告诉我们有对象发生了改变
watch: {
// 每当 question 发生变化时,该函数将会执行
question(newQuestion, oldQuestion) {
if (newQuestion.indexOf('?') > -1) {
this.getAnswer()
}
}
},
使用方式如下
怎么判断使用计算属性还是侦听器
如果一个数据在不发生改变的时候不需要再次处理数据以及额外的操作,那么我们使用计算属性
如果我们需要监控每一次的改变以及进行额外的操作,那么我们使用侦听器
可能语言的描述不太准确
但是如果你一旦开始使用并且熟练,那么你一定能区分到底使用哪种
不如我们来一个更简单的结论
如果能用计算属性完成你的想法,那么一一定不要使用侦听器
结语
撒花~