当前位置:首页 > VUE

vue 响应式实现

2026-03-08 08:45:04VUE

Vue 响应式实现原理

Vue 的响应式系统通过数据劫持结合发布-订阅模式实现,核心是利用 Object.defineProperty(Vue 2.x)或 Proxy(Vue 3.x)拦截数据变化,触发依赖更新。

Vue 2.x 实现方式

数据劫持 通过 Object.defineProperty 递归遍历对象属性,将属性转换为 getter/setter

function defineReactive(obj, key, val) {
  Object.defineProperty(obj, key, {
    get() {
      console.log('读取属性', key);
      return val;
    },
    set(newVal) {
      if (newVal !== val) {
        console.log('更新属性', key);
        val = newVal;
        // 触发依赖更新
        dep.notify();
      }
    }
  });
}

依赖收集 每个属性维护一个 Dep 实例(依赖管理器),在 getter 中收集当前依赖(Watcher):

class Dep {
  constructor() {
    this.subs = [];
  }
  addSub(sub) {
    this.subs.push(sub);
  }
  notify() {
    this.subs.forEach(sub => sub.update());
  }
}

观察者模式 Watcher 实例在初始化时触发 getter,将自身添加到 Dep 中:

class Watcher {
  constructor(vm, key, cb) {
    this.vm = vm;
    this.key = key;
    this.cb = cb;
    Dep.target = this; // 标记当前 Watcher
    this.value = vm[key]; // 触发 getter
    Dep.target = null; // 重置
  }
  update() {
    this.cb.call(this.vm, this.vm[this.key]);
  }
}

Vue 3.x 实现方式

Proxy 代理 使用 Proxy 直接监听整个对象,避免递归遍历:

function reactive(obj) {
  return new Proxy(obj, {
    get(target, key, receiver) {
      track(target, key); // 依赖收集
      return Reflect.get(target, key, receiver);
    },
    set(target, key, value, receiver) {
      Reflect.set(target, key, value, receiver);
      trigger(target, key); // 触发更新
      return true;
    }
  });
}

依赖管理 通过 WeakMapMap 建立靶点(target)与键(key)的依赖关系:

const targetMap = new WeakMap();
function track(target, key) {
  let depsMap = targetMap.get(target);
  if (!depsMap) {
    targetMap.set(target, (depsMap = new Map()));
  }
  let dep = depsMap.get(key);
  if (!dep) {
    depsMap.set(key, (dep = new Set()));
  }
  dep.add(activeEffect); // 当前激活的 effect
}

副作用函数 通过 effect 包装响应式操作:

vue 响应式实现

let activeEffect;
function effect(fn) {
  activeEffect = fn;
  fn(); // 执行时触发 track
  activeEffect = null;
}

注意事项

  • 数组处理:Vue 2.x 需重写数组方法(如 pushpop)实现响应式,Vue 3.x 的 Proxy 可直接监听数组变化。
  • 性能优化:Vue 3.x 的 Proxy 减少了递归劫持的开销,并支持懒代理(按需响应)。
  • 嵌套对象:Vue 2.x 需在初始化时递归劫持,Vue 3.x 在访问嵌套属性时才动态代理。

通过上述机制,Vue 实现了数据变化到视图更新的自动同步。

标签: vue
分享给朋友:

相关文章

vue实现分屏

vue实现分屏

Vue 实现分屏的方法 分屏功能通常用于展示多个独立内容区域,以下是几种常见的实现方式: 使用 CSS Grid 布局 通过 CSS Grid 可以轻松创建分屏布局,在 Vue 组件中直接应用样式:…

vue实现递归

vue实现递归

Vue 实现递归组件的方法 在 Vue 中实现递归组件通常用于处理树形结构数据(如菜单、评论列表、文件目录等)。以下是具体实现方法: 定义递归组件 通过 name 选项让组件可以递归调用自身: &…

vue compile 实现

vue compile 实现

Vue 编译实现原理 Vue 的编译过程将模板字符串转换为渲染函数,主要分为解析、优化和代码生成三个阶段。 解析阶段(Parse) 将模板字符串转换为抽象语法树(AST)。Vue 使用正则表达式和有…

vue实现分栏

vue实现分栏

Vue实现分栏的常见方法 使用CSS Flexbox布局 通过Flexbox可以快速实现分栏效果,适合大多数响应式布局场景 <template> <div class="con…

vue实现flbook

vue实现flbook

Vue 实现类似 Flbook 的翻页效果 要实现类似 Flbook 的翻页效果,可以使用 Vue 结合 CSS 动画和 JavaScript 事件处理。以下是实现方法: 安装依赖 需要安装 vue…

vue 实现滑动

vue 实现滑动

Vue 实现滑动效果的方法 在Vue中实现滑动效果可以通过多种方式,以下是几种常见的方法: 使用CSS过渡和动画 通过Vue的<transition>组件结合CSS过渡或动画实现滑动效果…