vue3的响应式具体是怎么实现的,你有看过源码吗

110 阅读2分钟

Vue 3 的响应式系统是基于 ES6 的ProxyReflect来实现的,其主要原理和关键源码如下:

核心原理

  • 使用Proxy代理对象Proxy可以拦截对象的各种操作,如读取属性、设置属性、删除属性等。Vue 3 利用Proxy来创建一个代理对象,对原始数据对象进行代理,从而能够监听对该对象的所有操作。
  • 依赖收集与触发更新:当访问代理对象的属性时,会进行依赖收集,将当前正在使用该属性的组件或函数记录下来。当属性值发生变化时,通过触发相应的更新函数,通知所有依赖该属性的地方进行更新。

关键源码解析

以下是简化后的 Vue 3 响应式系统核心源码示例,帮助理解其工作原理:

javascript

// 存储依赖的WeakMap
const targetMap = new WeakMap();

// 创建响应式对象
function reactive(target) {
  return new Proxy(target, {
    get(target, key, receiver) {
      // 收集依赖
      track(target, key);
      return Reflect.get(target, key, receiver);
    },
    set(target, key, value, receiver) {
      const result = Reflect.set(target, key, value, receiver);
      // 触发更新
      trigger(target, key);
      return result;
    }
  });
}

// 收集依赖
function track(target, key) {
  let depsMap = targetMap.get(target);
  if (!depsMap) {
    depsMap = new Map();
    targetMap.set(target, depsMap);
  }
  let dep = depsMap.get(key);
  if (!dep) {
    dep = new Set();
    depsMap.set(key, dep);
  }
  // 假设这里有一个全局变量activeEffect表示当前正在执行的副作用函数
  if (activeEffect) {
    dep.add(activeEffect);
  }
}

// 触发更新
function trigger(target, key) {
  const depsMap = targetMap.get(target);
  if (!depsMap) return;
  const dep = depsMap.get(key);
  if (!dep) return;
  // 执行所有依赖该属性的副作用函数
  dep.forEach(effect => effect());
}

在上述代码中,reactive函数用于创建一个响应式对象,通过Proxygetset拦截器来实现依赖收集和触发更新。track函数负责将当前的副作用函数(例如组件的渲染函数)收集到对应的属性依赖集合中。trigger函数则在属性值变化时,执行所有依赖该属性的副作用函数,从而实现响应式更新。

实际的 Vue 3 源码中,响应式系统更加复杂,还包括对RefComputed等功能的支持,以及对各种边界情况的处理,但核心原理大致如此。通过这种方式,Vue 3 实现了高效、精确的响应式数据管理,能够在数据变化时准确地更新相关的视图和逻辑。