洋葱模型是Vue框架中的一种数据依赖关系管理机制,用于实现响应式数据的更新和视图的重新渲染。 在Vue实例初始化时,每个计算属性都会关联一个懒加载的 Watcher,在访问计算属性时才会执行计算方法。
- 使用
Watcher的evaluate()方法时,会让计算属性直接依赖的属性收集当前计算属性Watcher,并建立起它们之间的依赖关系。 - 使用
Watcher的depend()方法时,则会将当前计算属性Watcher与其订阅的所有dep建立关联,使这些dep都能够收集上层Watcher。以此确保在依赖数据发生变化或上层Watcher发生变化时,能够触发当前计算属性Watcher的更新,从而保证计算属性的响应式更新。
这种机制好比一个洋葱,数据依赖就像层层剥开的皮,底层数据变化会逐层传递触发更新,最终实现视图的同步渲染,保证数据响应式和视图更新的一致性。
1# computed 嵌套调用
以下示例实现了一个 Vue 组件嵌套调用计算属性的案例,其中:
-
计算属性
point返回一个字符串[x, y],包含x和y的值。 -
计算属性
combined返回一个对象,包含start和end的值与计算属性point。
<template>
<p>嵌套的计算属性:{{ combined }}</p>
</template>
<script>
export default {
data() {
return {
start: 0, // 起点
end: 10, // 终点
x: 0, // x 坐标
y: 5, // y 坐标
};
},
computed: {
combined: function () {
return {
start: this.start,
end: this.end,
point: this.point,
};
},
point: function() {
return `[${this.x}, ${this.y}]`;
}
},
};
</script>
2# Watcher 调用步骤
Step 1. 初始化组件时,render-watcher 入栈
stack: [render-watcher]
Step 2. 当 render 函数访问 combined 计算属性时,执行 combined-watcher 的 evaluate() 方法并入栈。
stack: [render-watcher, combined-watcher]render-watcher: [combined]
Step 3. 当执行 combined-watcher 的 get() 方法时,其直接依赖的 start 和 end 会去收集当前的 combined-watcher;之后又访问 point 计算属性,执行 point-watcher 的 evaluate() 方法并入栈。
stack: [render-watcher, combined-watcher, point-watcher]render-watcher: [combined]combined-watcher:[start, end, point]
Step 4. 当执行 point-watcher 的 get() 方法时,其直接依赖的 x 和 y 会去收集当前的 point-watcher;
stack: [render-watcher, combined-watcher, point-watcher]render-watcher: [combined]combined-watcher:[start, end, point]point-watcher:[x, y]
Step 5. point-watcher 出栈并执行 depend() 方法,让 point-watcher 订阅的 dep 再去收集当前 combined-watcher 依赖。
stack: [render-watcher, combined-watcher]render-watcher: [combined]combined-watcher:[start, end, x, y]
Step 6. combined-watcher 出栈并执行 depend() 方法,让 combined-watcher 订阅的 dep 再去收集当前 render-watcher 依赖,至此完成了视图更新的全过程。
stack: [render-watcher]render-watcher: [start, end, x, y]