Vue 3 响应式系统小结
- 1.核心概念
- 1.1 Proxy和Reflect
- 1.2 响应式API
- 1.3 依赖收集与更新触发
- 1.4 触发更新(Triggering Updates):
- 1.5 副作用函数(Effect)
- 1.6 计算属性和观察者
- 1.7 EffectScope
- 1.8 性能优化:
- 2. 手动实现简单响应式系统
- 3. 发散思考
Vue 3 的响应式系统利用现代 JavaScript 的特性,如 Proxy 和 Reflect,为开发者提供了一个强大且灵活的工具集,以简化响应式编程。这一节回顾了我们学习的关键概念,并展示了如何手动构建一个简单的响应式系统。
1.核心概念
1.1 Proxy和Reflect
Vue 3 采用 Proxy 来拦截对象操作,配合 Reflect 保证操作的默认行为。这使得 Vue 能够在数据访问或修改时执行自定义逻辑,实现自动的依赖跟踪和更新触发。
1.2 响应式API
通过 reactive、ref 等 API,Vue 允许开发者把普通对象转换成响应式对象,实现数据的自动更新。
1.3 依赖收集与更新触发
Vue 内部通过 track 和 trigger 函数管理依赖关系,确保数据变化时能自动通知并执行相关的副作用函数。
1.4 触发更新(Triggering Updates):
当响应式数据被修改时,Vue 通过trigger函数查找所有依赖于这个数据的副作用函数,并重新执行它们。这样,基于这些数据的视图或其他副作用就会被更新。
1.5 副作用函数(Effect)
Vue 3通过effect函数包装副作用(如渲染函数、计算属性等),使其能够自动响应数据的变化。每个副作用在执行时都会被ReactiveEffect类的实例封装,这个实例记录了副作用函数以及它所依赖的数据。
1.6 计算属性和观察者
计算属性和观察者也是通过副作用系统实现的。计算属性(computed)和观察者(watch)提供了更细粒度的响应式控制,优化性能同时保持数据更新的逻辑清晰。
1.7 EffectScope
effectScope 管理副作用的生命周期,尤其是在组件卸载时自动停止副作用,避免内存泄漏。
1.8 性能优化:
Vue 3的响应式系统使用了诸如WeakMap和Map这样的原生数据结构来存储依赖关系,减少了内存的使用,并优化了垃圾回收。同时,通过避免不必要的副作用执行和精细的依赖追踪,提高了更新的效率。
2. 手动实现简单响应式系统
在完整的学习了Vue3源码响应式系统部分之后,我们尝试以手动创建一个简化版的响应式系统来加深理解:
//响应式逻辑
let activeEffect = null;
const targetMap = new WeakMap();
const reactive = (target) => {
return new Proxy(target, handler);
}
const handler = {
get(target, property, receiver) {
track(target, property);
return Reflect.get(target, property, receiver); // 确保返回属性的值
},
set(target, property, value, receiver) {
const result = Reflect.set(target, property, value, receiver); // 设置新值
trigger(target, property, value);
return result;
}
}
const track = (target, property) => {
if (!activeEffect) return;
let depsMap = targetMap.get(target);
if (!depsMap) {
depsMap = new Map();
targetMap.set(target, depsMap);
}
let deps = depsMap.get(property);
if (!deps) {
deps = new Set(); // 使用 Set 存储唯一的副作用函数
depsMap.set(property, deps);
}
deps.add(activeEffect);
}
const trigger = (target, property) => {
const depsMap = targetMap.get(target)
if (!depsMap) {
return;
}
const deps = depsMap.get(property);
deps.forEach(effectFn => {
effectFn.run();
})
}
class ReactiveEffect {
constructor(fn) {
this.fn=fn;
}
run() {
try {
activeEffect = this;
this.fn();
} finally {
activeEffect = null;
}
}
}
const effect = (fn) => {
const _effect = new ReactiveEffect(fn);
_effect.run();
return _effect;
}
//应用
const status = reactive({
count: 0
});
effect(() => {
console.log(status.count);
});
status.count++;
//执行和输出:
//0
//0
3. 发散思考
Vue的响应式系统和Backbone中的数据监听、发布-订阅模式在目的上确实非常相似,都是为了实现数据变化时自动更新视图或执行某些操作。它们都遵循了观察者模式的基本原则,即当数据(被观察者)发生变化时,能够自动通知所有依赖于这些数据的订阅者(观察者),并触发相应的更新逻辑。
Vue 的响应式系统与 Backbone 等传统模式的主要区别在于自动化的依赖追踪与更新触发机制。Vue的响应式系统利用ES6的Proxy和内部的依赖追踪机制来自动捕获依赖关系,并在响应式数据变化时自动触发更新。Vue 的设计使得开发者能够专注于业务逻辑,而无需手动管理数据监听和更新,极大地提升了开发效率和应用性能。