当前位置:首页 > VUE

vue响应式简单实现

2026-02-24 13:04:00VUE

响应式原理概述

Vue的响应式系统通过数据劫持结合发布-订阅模式实现。核心是利用Object.defineProperty(Vue 2)或Proxy(Vue 3)拦截对象属性的读写操作,在数据变化时自动触发依赖更新。

vue响应式简单实现

Vue 2 实现方式

基于Object.defineProperty实现数据劫持:

vue响应式简单实现

function defineReactive(obj, key, val) {
  // 递归处理嵌套对象
  observe(val);
  const dep = new Dep(); // 依赖管理

  Object.defineProperty(obj, key, {
    get() {
      Dep.target && dep.addSub(Dep.target); // 收集依赖
      return val;
    },
    set(newVal) {
      if (newVal === val) return;
      observe(newVal); // 新值为对象时递归劫持
      val = newVal;
      dep.notify(); // 通知更新
    }
  });
}

function observe(obj) {
  if (typeof obj !== 'object' || obj === null) return;
  new Observer(obj);
}

class Observer {
  constructor(obj) {
    if (Array.isArray(obj)) {
      // 数组响应式需特殊处理(重写方法)
    } else {
      Object.keys(obj).forEach(key => defineReactive(obj, key, obj[key]));
    }
  }
}

依赖管理类

class Dep {
  constructor() {
    this.subs = [];
  }
  addSub(sub) {
    this.subs.push(sub);
  }
  notify() {
    this.subs.forEach(sub => sub.update());
  }
}
Dep.target = null; // 静态属性指向当前Watcher

Vue 3 实现方式

基于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;
    }
  });
}

// 依赖跟踪与触发
const targetMap = new WeakMap();
function track(target, key) {
  if (!activeEffect) return;
  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);
}

function trigger(target, key) {
  const depsMap = targetMap.get(target);
  if (!depsMap) return;
  depsMap.get(key)?.forEach(effect => effect());
}

简单Watcher实现

let activeEffect;
class Watcher {
  constructor(fn) {
    this.fn = fn;
    this.run();
  }
  run() {
    activeEffect = this.fn;
    this.fn();
    activeEffect = null;
  }
  update() {
    this.run();
  }
}

// 使用示例
const data = reactive({ count: 0 });
new Watcher(() => console.log('Count:', data.count));
data.count++; // 自动触发日志输出

注意事项

  1. 性能优化:Proxy相比Object.defineProperty无需递归初始化所有属性,按需响应。
  2. 数组处理:Vue 2需重写数组方法(push/pop等),Vue 3的Proxy可直接拦截数组索引变化。
  3. 局限性:Vue 2无法检测新增/删除属性(需用Vue.set/Vue.delete),Proxy无此限制。

通过上述代码可实现基础的响应式系统,实际Vue源码还包含虚拟DOM、批量更新等优化逻辑。

标签: 简单vue
分享给朋友:

相关文章

vue实现div

vue实现div

Vue 实现 DIV 元素的方法 在 Vue 中实现 DIV 元素可以通过多种方式,以下是几种常见的实现方法: 使用模板语法 在 Vue 的模板中直接使用 HTML 的 <div> 标签…

vue 实现递归

vue 实现递归

Vue 实现递归组件的方法 在 Vue 中实现递归组件通常用于处理树形结构数据,例如菜单、评论列表或文件目录。以下是实现递归组件的关键步骤: 定义递归组件 递归组件需要设置 name 属性,以便在模…

vue实现RTMP

vue实现RTMP

Vue 中实现 RTMP 流播放 RTMP(Real-Time Messaging Protocol)是一种用于实时音视频流传输的协议。在 Vue 中实现 RTMP 播放通常需要借助第三方库或播放器。…

vue实现flbook

vue实现flbook

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

vue sku 实现

vue sku 实现

Vue SKU 实现方案 在电商系统中,SKU(Stock Keeping Unit)是商品的最小库存单位,通常由多个属性组合而成(如颜色、尺寸等)。以下是基于 Vue 的实现方案。 数据结构设计…

vue实现投票

vue实现投票

Vue实现投票功能 数据准备 在Vue组件的data中定义投票相关数据,包括选项列表和当前选中状态: data() { return { options: [ { id: 1…