Vue 3 的响应式系统是整个框架的核心,通过 Proxy 对象实现了数据和视图之间的双向绑定。下面我将详细分析 Vue 3 响应式系统的原理,包括代码示例和详细的解释。
1. 创建响应式数据对象:
首先,我们使用 reactive
函数来创建响应式数据对象。这个函数接受一个普通的 JavaScript 对象,并返回一个代理对象,该代理对象包含了数据对象的属性和拦截器,用于侦测属性的访问和修改。
const state = reactive({
count: 0
});
2. 代理对象的 get 拦截器(依赖追踪):
代理对象通过 Proxy 拦截器拦截对数据属性的访问。在 get 拦截器中,我们会进行依赖追踪,即收集当前激活的计算属性函数(effect)对属性的依赖。
代码语言:javascript复制let activeEffect = null;
function effect(fn) {
activeEffect = fn;
fn(); // 执行计算属性函数
activeEffect = null;
}
function track(target, key) {
if (activeEffect) {
// 收集依赖
activeEffect.dependencies.push(key);
}
}
const reactiveHandler = {
get(target, key) {
// 依赖追踪
track(target, key);
return target[key];
}
};
const state = reactive({
count: 0
});
3. 创建计算属性:
计算属性是基于响应式数据对象的派生属性,其值是通过计算函数获取的。在 Vue 3 中,可以使用 computed
函数来创建计算属性。
function computed(getter) {
let value;
let dirty = true; // 初始标记为需要重新计算
const effect = () => {
if (dirty) {
value = getter(); // 执行计算函数
dirty = false;
}
};
effect.dependencies = []; // 存储依赖属性
effect(); // 初始执行计算属性函数
return {
effect,
value,
};
}
const double = computed(() => state.count * 2);
4. 计算属性的依赖收集:
在计算属性的 getter
函数中,依赖属性的访问会触发代理对象的 get
拦截器,进而触发依赖追踪。
const double = computed(() => state.count * 2);
// 此时触发依赖追踪,将 state.count 加入 double 的依赖列表
5. 触发计算属性的重新计算:
当依赖属性发生变化时,触发计算属性的重新计算。这是通过触发函数(trigger)来实现的。
代码语言:javascript复制function trigger(target, key) {
// 找到依赖此属性的计算属性
const effects = target[key].dependencies;
if (effects) {
effects.forEach(effect => {
effect.dirty = true; // 标记为需要重新计算
});
}
}
const state = reactive({
count: 0
});
const double = computed(() => state.count * 2);
console.log(double.value); // 输出 0
state.count = 2; // 数据变化,触发计算属性重新计算
console.log(double.value); // 输出 4,已经重新计算
6. 异步更新和调度器:
Vue 3 的响应式系统支持异步更新,以提高性能。它还引入了调度器(scheduler)的概念,可以控制计算属性和观察者何时执行。
代码语言:javascript复制function computed(getter, options) {
const runner = effect(getter, {
lazy: true,
...options
});
const computed = {
effect: runner,
value: undefined
};
return computed;
}
调度器可以用来控制计算属性和观察者的执行时机,以减少计算的重复和提高性能。
这就是 Vue 3 响应式系统的基本原理,它通过 Proxy 对象和依赖追踪来实现数据和视图的双向绑定,以及计算属性和观察者来处理派生数据和副作用。这个系统使 Vue 3 更高效、更灵活,并能够更好地处理复杂的应用场景。
我正在参与2023腾讯技术创作特训营第三期有奖征文,组队打卡瓜分大奖!