当前位置:首页 > VUE

vue数据响应式实现

2026-02-23 13:16:15VUE

Vue 数据响应式实现原理

Vue 的数据响应式是通过 Object.defineProperty(Vue 2.x)或 Proxy(Vue 3.x)实现的,核心是依赖收集和派发更新。

Vue 2.x 的实现

数据劫持 通过 Object.defineProperty 对对象的属性进行劫持,在 getter 中收集依赖,在 setter 中触发更新。

function defineReactive(obj, key, val) {
  const dep = new Dep(); // 依赖管理器

  Object.defineProperty(obj, key, {
    get() {
      if (Dep.target) {
        dep.depend(); // 收集依赖
      }
      return val;
    },
    set(newVal) {
      if (newVal === val) return;
      val = newVal;
      dep.notify(); // 触发更新
    }
  });
}

依赖收集 每个响应式属性都有一个 Dep 实例,用于管理依赖(即 Watcher 实例)。当数据被访问时,当前 Watcher 会被添加到 Dep 中。

vue数据响应式实现

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

  depend() {
    if (Dep.target) {
      this.subs.push(Dep.target);
    }
  }

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

Watcher Watcher 是观察者,负责执行更新操作(如渲染视图)。在初始化时,会将当前 Watcher 设置为 Dep.target,触发 getter 收集依赖。

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

  update() {
    this.value = this.vm[this.key];
    this.cb(this.value);
  }
}

Vue 3.x 的实现

Vue 3.x 使用 Proxy 替代 Object.defineProperty,解决了 Vue 2.x 中无法检测数组和对象新增属性的问题。

vue数据响应式实现

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

依赖管理 Vue 3.x 使用 effect 替代 Watcher,通过 tracktrigger 管理依赖。

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;
  const dep = depsMap.get(key);
  if (dep) {
    dep.forEach(effect => effect());
  }
}

let activeEffect;

function effect(fn) {
  activeEffect = fn;
  fn();
  activeEffect = null;
}

总结

  • Vue 2.x:通过 Object.defineProperty 劫持数据,结合 DepWatcher 实现依赖收集和派发更新。
  • Vue 3.x:通过 Proxy 实现更全面的数据劫持,使用 effecttracktrigger 管理依赖,性能更好且支持更多操作。

标签: 数据vue
分享给朋友:

相关文章

vue实现下载暂停

vue实现下载暂停

Vue实现下载暂停功能 在Vue中实现下载暂停功能,通常需要结合XMLHttpRequest或Fetch API的AbortController来控制请求中断。以下是具体实现方法: 使用XMLHtt…

vue实现多选题

vue实现多选题

Vue实现多选题的方法 使用Vue实现多选题功能,可以通过v-model绑定数组、动态渲染选项、以及处理选中状态来实现。以下是一个完整的实现示例: 基础实现代码 <template>…

vue实现用户信息表

vue实现用户信息表

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

vue实现视窗

vue实现视窗

Vue 实现视窗功能 在 Vue 中实现视窗功能通常涉及监听浏览器窗口大小变化、响应式布局或创建自定义弹窗组件。以下是几种常见实现方式: 监听浏览器窗口大小变化 使用 Vue 的 mounted…

vue实现iframe

vue实现iframe

Vue 中实现 iframe 的方法 在 Vue 项目中,可以通过多种方式实现 iframe 的嵌入。以下是几种常见的方法: 使用原生 HTML iframe 标签 直接在 Vue 组件的模板中使…

vue实现语音

vue实现语音

Vue 实现语音功能的方法 使用 Web Speech API Vue 可以结合 Web Speech API 实现语音识别和合成功能。Web Speech API 包含 SpeechRecognit…