当前位置:首页 > VUE

vue数据劫持实现

2026-03-28 08:08:44VUE

Vue 数据劫持实现原理

Vue 的数据劫持核心是通过 Object.defineProperty(Vue 2.x)或 Proxy(Vue 3.x)实现的响应式系统。以下是具体实现方式:

基于 Object.defineProperty 的实现(Vue 2.x)

数据劫持初始化 通过遍历对象的属性,递归地将每个属性转换为 getter/setter

function observe(data) {
  if (typeof data !== 'object' || data === null) return;
  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); // 递归处理嵌套对象
  Object.defineProperty(obj, key, {
    get() {
      console.log(`读取 ${key}`);
      return val;
    },
    set(newVal) {
      if (newVal === val) return;
      console.log(`设置 ${key}`);
      val = newVal;
      observe(newVal); // 新值为对象时继续劫持
    }
  });
}

数组方法劫持 重写数组的 pushpop 等原型方法以触发更新:

vue数据劫持实现

const arrayProto = Array.prototype;
const arrayMethods = Object.create(arrayProto);
['push', 'pop', 'shift'].forEach(method => {
  arrayMethods[method] = function(...args) {
    const result = arrayProto[method].apply(this, args);
    console.log(`数组变更:${method}`);
    return result;
  };
});

基于 Proxy 的实现(Vue 3.x)

Proxy 可以直接拦截整个对象,无需递归初始化:

function reactive(data) {
  if (typeof data !== 'object' || data === null) return data;
  return new Proxy(data, {
    get(target, key, receiver) {
      console.log(`读取 ${key}`);
      return Reflect.get(target, key, receiver);
    },
    set(target, key, value, receiver) {
      console.log(`设置 ${key}`);
      return Reflect.set(target, key, value, receiver);
    },
    deleteProperty(target, key) {
      console.log(`删除 ${key}`);
      return Reflect.deleteProperty(target, key);
    }
  });
}

嵌套对象处理 Proxy 自动处理嵌套对象,无需显式递归:

vue数据劫持实现

const obj = reactive({ 
  nested: { a: 1 } 
});
obj.nested.a = 2; // 自动触发 setter

差异对比

  1. 初始化性能

    • Object.defineProperty 需要递归遍历所有属性。
    • Proxy 直接代理整个对象,按需触发。
  2. 数组支持

    • Object.defineProperty 需特殊处理数组方法。
    • Proxy 天然支持数组索引和 length 变化。
  3. 新属性响应

    • Object.defineProperty 需手动调用 Vue.set
    • Proxy 自动检测动态添加的属性。

实现注意事项

  • 循环引用:需使用 WeakMap 存储已代理对象避免重复。
  • 性能优化:Vue 3 的 Proxy 实现中通过 Reflect 避免不必要的操作。
  • 浏览器兼容性:Proxy 无法被 polyfill,Vue 3 放弃支持 IE11。

以上实现省略了依赖收集和派发更新的细节(如 Dep/Watcher 机制),但展示了数据劫持的核心逻辑。

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

相关文章

vue实现一个标签选择

vue实现一个标签选择

Vue 标签选择组件实现 基础实现 使用 Vue 的 v-for 和 v-model 指令可以快速实现标签选择功能: <template> <div class="tag-se…

vue实现白板

vue实现白板

Vue实现白板功能 使用Vue实现白板功能可以通过HTML5的Canvas API结合Vue的响应式特性来完成。以下是实现白板功能的关键步骤: 安装依赖 在Vue项目中安装必要的依赖,如vue-dr…

vue watch实现

vue watch实现

在 Vue 中实现 watch 监听数据变化 Vue 的 watch 选项用于监听数据变化并执行相应的回调函数。以下是几种常见的实现方式: 基础用法 export default { data(…

vue实现爬虫

vue实现爬虫

Vue 实现爬虫的基本思路 Vue.js 本身是一个前端框架,主要用于构建用户界面。要实现爬虫功能,通常需要结合后端技术或浏览器自动化工具。以下是几种常见的方法: 方法一:Vue + Node.js…

vue 实现协同

vue 实现协同

Vue 实现协同编辑的方案 协同编辑指多个用户同时编辑同一文档并实时同步更改。Vue 结合相关库和技术可轻松实现该功能。 使用 WebSocket 实现实时通信 WebSocket 提供全双工通信,…

vue实现分站

vue实现分站

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