当前位置:首页 > VUE

vue响应式简单实现

2026-02-24 13:04:00VUE

响应式原理概述

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

Vue 2 实现方式

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

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的改进方案:

vue响应式简单实现

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异步组建实现原理

vue异步组建实现原理

Vue 异步组件实现原理 Vue 的异步组件允许将组件按需加载,通常用于代码分割或延迟加载非关键组件。其核心原理基于 Promise 和动态导入。 基本实现方式 通过 defineAsyncComp…

实现vue模版

实现vue模版

Vue 模板的基本结构 Vue 模板基于 HTML 语法,通过 Vue 的指令和插值实现动态渲染。以下是一个基础模板示例: <template> <div id="app"…

vue实现handsontable

vue实现handsontable

Vue 中实现 Handsontable 要在 Vue 项目中集成 Handsontable,可以使用官方提供的 @handsontable/vue 封装库。以下是一个完整的实现步骤。 安装依赖 确…

vue 实现上传

vue 实现上传

Vue 实现文件上传 使用 Vue 实现文件上传可以通过原生 HTML 的 <input type="file"> 或第三方库(如 axios、vue-upload-component)完…

vue实现分站

vue实现分站

Vue 实现分站的方案 在 Vue 中实现分站功能通常涉及路由配置、环境变量管理和动态加载资源。以下是几种常见的实现方式: 基于路由的分站实现 通过 Vue Router 配置多路由,区分不同站点的…

vue简单实现

vue简单实现

Vue 简单实现示例 以下是一个使用 Vue.js 创建简单应用的示例,涵盖基本功能如数据绑定、事件处理和组件化。 基础 HTML 结构 <!DOCTYPE html> <html…