面试题答案
一键面试Vue追踪计算属性依赖项及重新计算流程
- 追踪依赖项
- 依赖收集:Vue使用Object.defineProperty()方法对数据对象的属性进行劫持。当访问计算属性时,计算属性内部会读取依赖的数据。在读取依赖数据的过程中,Vue会在当前的渲染Watcher(或计算Watcher)与依赖数据之间建立联系。具体来说,每个数据属性都有一个Dep对象,Dep对象维护了一个依赖它的Watcher列表。当计算属性的Watcher访问依赖数据时,该Watcher就会被添加到依赖数据的Dep的Watcher列表中,这就是依赖收集的过程。例如:
<template>
<div>
<p>{{ computedValue }}</p>
</div>
</template>
<script>
export default {
data() {
return {
message: 'Hello'
};
},
computed: {
computedValue() {
return this.message.split('').reverse().join('');
}
}
};
</script>
在上述代码中,当访问computedValue
计算属性时,会读取message
数据。此时,computedValue
对应的Watcher就会被收集到message
数据的Dep中。
- 依赖项更新后重新计算流程
- 通知更新:当依赖的数据发生变化时,会触发数据的setter方法。在setter方法中,会通知依赖数据的Dep对象。Dep对象会遍历它维护的Watcher列表,通知每个Watcher数据发生了变化。
- 重新计算:计算属性对应的Watcher收到通知后,会将自己的dirty标志设为true。在下一次访问该计算属性时,由于dirty为true,计算属性会重新执行函数,重新求值,并将结果缓存起来,同时将dirty标志设为false。例如,上述代码中如果
message
数据发生变化,computedValue
的Watcher收到通知,设dirty为true。再次访问computedValue
时,就会重新计算message.split('').reverse().join('')
的值,并缓存结果,同时将dirty设为false。
通过这种依赖收集和通知更新的机制,Vue能够高效地追踪计算属性的依赖项,并在依赖项变化时及时重新计算计算属性的值。