当前位置:首页 > VUE

实现简易vue响应式

2026-01-21 15:10:14VUE

实现简易 Vue 响应式系统

Vue 的响应式系统核心是通过 Object.definePropertyProxy 拦截数据变化,并结合依赖收集与派发更新机制实现。以下是一个基于 Object.defineProperty 的简化实现:

数据劫持(Observer)

通过递归遍历对象属性,将其转换为响应式:

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

class Observer {
  constructor(data) {
    this.walk(data);
  }

  walk(data) {
    Object.keys(data).forEach(key => {
      defineReactive(data, key, data[key]);
    });
  }
}

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;
      val = newVal;
      observe(newVal); // 新值是对象时继续劫持
      dep.notify(); // 触发更新
    }
  });
}

依赖管理(Dep)

管理所有依赖(Watcher)并在数据变化时通知:

class Dep {
  constructor() {
    this.subs = [];
  }

  addSub(sub) {
    this.subs.push(sub);
  }

  notify() {
    this.subs.forEach(sub => sub.update());
  }
}

Dep.target = null; // 全局标记当前正在计算的Watcher

观察者(Watcher)

封装依赖更新逻辑:

class Watcher {
  constructor(vm, key, cb) {
    this.vm = vm;
    this.key = key;
    this.cb = cb;
    Dep.target = this;
    this.oldValue = vm[key]; // 触发getter收集依赖
    Dep.target = null;
  }

  update() {
    const newValue = this.vm[this.key];
    if (newValue !== this.oldValue) {
      this.cb(newValue);
      this.oldValue = newValue;
    }
  }
}

使用示例

const data = { count: 1 };
observe(data);

new Watcher(data, 'count', (val) => {
  console.log(`count更新为: ${val}`);
});

data.count = 2; // 输出: "count更新为: 2"

注意事项

  1. 数组变异方法需要特殊处理(如 push/pop 等)
  2. 现代 Vue 版本已改用 Proxy 实现,可避免 Object.defineProperty 的局限性(如新增属性检测)
  3. 实际实现还需处理虚拟DOM、批量更新等复杂逻辑

实现简易vue响应式

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

相关文章

vue实现文件下载

vue实现文件下载

使用 a 标签下载文件 通过动态创建 a 标签并触发点击事件实现文件下载。适用于直接下载服务器上的静态文件或 Blob 数据。 downloadFile(url, fileName) { c…

vue实现按钮组轮换

vue实现按钮组轮换

实现按钮组轮换的方法 在Vue中实现按钮组轮换效果可以通过动态绑定类和事件处理来完成。以下是一种常见的实现方式: 模板部分 <template> <div class="bu…

vue实现收起展开面板

vue实现收起展开面板

实现收起展开面板的方法 在Vue中实现收起展开面板功能可以通过多种方式完成,以下是几种常见的实现方法: 使用v-show或v-if控制显示隐藏 利用Vue的指令可以轻松实现面板的展开和收起:…

vue 实现在线预览

vue 实现在线预览

Vue 实现在线预览的常见方法 使用 iframe 嵌入 通过 iframe 标签可以嵌入多种类型的文件,如 PDF、图片、网页等。需要确保文件地址可访问。 <template> &…

vue实现用户信息表

vue实现用户信息表

Vue 实现用户信息表的方法 使用 Vue CLI 创建项目 安装 Vue CLI 并初始化项目: npm install -g @vue/cli vue create user-info-tab…

vue实现倒计时抢券

vue实现倒计时抢券

Vue 实现倒计时抢券功能 核心逻辑 倒计时抢券功能需要结合时间计算、状态管理和界面交互。通过 Vue 的响应式特性和生命周期钩子,可以高效实现这一需求。 实现步骤 1. 数据准备 在 Vue 组…