当前位置:首页 > VUE

vue怎么实现数据劫持

2026-02-21 05:37:44VUE

Vue 数据劫持的实现原理

Vue 的数据劫持主要通过 Object.definePropertyProxy 实现,用于监听数据变化并触发视图更新。以下是核心实现方式:

使用 Object.defineProperty

Vue 2.x 版本采用 Object.defineProperty 对对象的属性进行劫持,通过 getter 和 setter 拦截读写操作。

function defineReactive(obj, key, val) {
  Object.defineProperty(obj, key, {
    enumerable: true,
    configurable: true,
    get() {
      console.log(`读取属性 ${key}`);
      return val;
    },
    set(newVal) {
      if (newVal === val) return;
      console.log(`设置属性 ${key} 为 ${newVal}`);
      val = newVal;
    }
  });
}

const data = { name: 'Vue' };
defineReactive(data, 'name', data.name);
data.name = 'React'; // 触发 setter
  • 局限性:无法监听新增/删除的属性,需配合 Vue.setVue.delete 使用。

使用 Proxy

Vue 3.x 改用 Proxy 实现数据劫持,支持对整个对象的拦截,包括新增或删除属性。

function reactive(obj) {
  return new Proxy(obj, {
    get(target, key) {
      console.log(`读取属性 ${key}`);
      return Reflect.get(target, key);
    },
    set(target, key, value) {
      if (target[key] === value) return true;
      console.log(`设置属性 ${key} 为 ${value}`);
      return Reflect.set(target, key, value);
    },
    deleteProperty(target, key) {
      console.log(`删除属性 ${key}`);
      return Reflect.deleteProperty(target, key);
    }
  });
}

const data = reactive({ name: 'Vue' });
data.name = 'React'; // 触发 set
delete data.name;    // 触发 deleteProperty
  • 优势:支持动态属性增删,性能更优。

数组的劫持处理

Vue 对数组方法(如 pushpop)进行重写,通过原型链拦截实现响应式。

const arrayProto = Array.prototype;
const arrayMethods = Object.create(arrayProto);

['push', 'pop', 'shift'].forEach(method => {
  const original = arrayProto[method];
  arrayMethods[method] = function(...args) {
    console.log(`数组方法 ${method} 被调用`);
    return original.apply(this, args);
  };
});

const arr = [];
arr.__proto__ = arrayMethods;
arr.push(1); // 触发拦截

依赖收集与派发更新

Vue 通过 Dep(依赖收集器)和 Watcher(观察者)实现数据变化到视图更新的联动。

  1. Dep:每个响应式属性对应一个 Dep 实例,用于存储依赖的 Watcher。
  2. Watcher:在 getter 中收集依赖,在 setter 中通知 Watcher 更新。
class Dep {
  constructor() {
    this.subscribers = [];
  }
  depend() {
    if (target && !this.subscribers.includes(target)) {
      this.subscribers.push(target);
    }
  }
  notify() {
    this.subscribers.forEach(sub => sub());
  }
}

let target = null;
function watchEffect(cb) {
  target = cb;
  cb();
  target = null;
}

总结

  • Vue 2.x 使用 Object.defineProperty 劫持对象属性,需额外处理数组和动态属性。
  • Vue 3.x 使用 Proxy 提供更全面的劫持能力,性能更优。
  • 依赖收集机制确保数据变化时精确更新相关视图。

vue怎么实现数据劫持

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

相关文章

vue实现表格多行修改

vue实现表格多行修改

实现多行编辑表格 在Vue中实现表格的多行编辑功能,可以通过以下方法完成。这里以Element UI的表格组件为例,但思路适用于其他UI库或原生实现。 数据准备 定义表格数据和编辑状态管理变量:…

vue实现无线滚动列表

vue实现无线滚动列表

无限滚动列表的实现方法 在Vue中实现无限滚动列表通常结合监听滚动事件和动态加载数据。以下是几种常见方法: 使用自定义指令 创建自定义指令v-infinite-scroll监听滚动事件: Vu…

vue实现下拉刷新组件

vue实现下拉刷新组件

实现下拉刷新组件的核心思路 下拉刷新功能通常通过监听触摸事件、滚动位置和动画效果实现。Vue中可以利用自定义指令或封装组件完成,以下为两种常见实现方式。 基于自定义指令的实现 创建指令监听触摸事件,…

vue实现菜单栏锚点

vue实现菜单栏锚点

实现锚点菜单的基本思路 在Vue中实现菜单栏锚点功能,主要涉及两个方面:创建可跳转的锚点位置,以及菜单项的点击滚动控制。通过监听滚动事件可以高亮当前可见区域的对应菜单项。 创建页面锚点位置 在需要跳…

vue实现一个tab栏

vue实现一个tab栏

Vue 实现 Tab 栏 基础实现(选项式 API) <template> <div class="tab-container"> <div class="t…

vue实现打印二维码

vue实现打印二维码

安装二维码生成库 使用 qrcode 或 vue-qrcode 库生成二维码。通过 npm 安装: npm install qrcode vue-qrcode 生成二维码 在 Vue 组件中引…