面试题库 词条目录
前端Wiki/面试题库/框架与工程化/框架原理

框架响应式原理

响应式原理是框架核心。Vue2 用 Object.defineProperty:给每个属性定义 getter / setter,getter 收集依赖(Watcher),setter 通知更新;缺陷是新增属性、数组下标修改监听不到,需要 $set 兜底。Vue3 换成 Proxy:代理整个对象,拦截 get / set / deleteProperty / 数组方法,一次到位且性能更好(惰性收集,只有被读取的属性才建立依赖)。

React 的“响应式”是另一套:setState 触发 re-render,Fiber 架构把渲染拆成可中断的小任务,双缓存树(current → workInProgress)实现增量渲染。依赖追踪是 React 的弱项,所以需要 useMemo / useCallback / memo 手动声明依赖,React Compiler 正试图自动化这一步。

  • Vue2:Object.defineProperty 逐属性劫持,新增属性与数组下标需 $set
  • Vue3:Proxy 代理整个对象,惰性收集依赖,性能与能力双升级
  • React:setState 触发整树 diff,Fiber 可中断渲染,依赖需手动 memo
JS
// 手写 mini 响应式(Vue3 核心思路)
const targetMap = new WeakMap();   // 对象 -> 属性 -> 依赖集合
let activeEffect = null;

function effect(fn) {
  activeEffect = fn;
  fn();                             // 执行时触发 getter,完成依赖收集
  activeEffect = null;
}

function reactive(obj) {
  return new Proxy(obj, {
    get(t, key, receiver) {
      // 依赖收集:把当前 effect 记到这个属性上
      if (activeEffect) {
        let depsMap = targetMap.get(t);
        if (!depsMap) targetMap.set(t, (depsMap = new Map()));
        let dep = depsMap.get(key);
        if (!dep) depsMap.set(key, (dep = new Set()));
        dep.add(activeEffect);
      }
      return Reflect.get(t, key, receiver);
    },
    set(t, key, val, receiver) {
      const res = Reflect.set(t, key, val, receiver);
      const dep = targetMap.get(t)?.get(key);   // 派发更新
      dep?.forEach(eff => eff());
      return res;
    },
  });
}

// 验证:数据变 → 与之相关的 effect 自动跑
const state = reactive({ count: 0, name: "小明" });
effect(() => console.log("count 变成", state.count));  // count 变成 0
state.count++;                        // count 变成 1:setter 找到依赖并触发
state.name = "小红";                  // 无 effect 订阅,无输出(惰性精准)
本节要点响应式 = 数据劫持 + 依赖收集 + 派发更新;Vue3 用 Proxy 解决了 Vue2 的数组与新增属性盲区。
🔗 相关词条VueReact原型链