当前位置:首页 > VUE

vue怎么实现数据劫持

2026-02-21 05:37:44VUE

Vue 数据劫持的实现原理

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

使用 Object.defineProperty

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

vue怎么实现数据劫持

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 实现数据劫持,支持对整个对象的拦截,包括新增或删除属性。

vue怎么实现数据劫持

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 实现菜单可以通过多种方式,以下是几种常见的方法: 使用 Vue Router 实现动态路由菜单 通过 Vue Router 可以动态生成菜单,根据路由配置自动渲…

vue实现https

vue实现https

Vue 中实现 HTTPS 的步骤 在 Vue 项目中实现 HTTPS 主要涉及开发环境配置和生产环境部署。以下是具体方法: 开发环境配置(Vue CLI 或 Vite) 使用 mkcert 生成…

vue实现sso

vue实现sso

Vue 实现 SSO(单点登录)方案 单点登录(SSO)允许用户通过一次登录访问多个相关系统。以下是基于 Vue 的实现方案: 使用 OAuth2/OpenID Connect 协议 OAuth2…

实现简易vue

实现简易vue

实现简易 Vue 的核心思路 Vue 的核心功能包括数据响应式、模板编译和虚拟 DOM。以下是一个简易实现方案,涵盖核心功能模块。 数据响应式系统 通过 Object.defineProperty…

vue 实现fadeout

vue 实现fadeout

Vue 实现淡出效果 在 Vue 中实现淡出(fade-out)效果可以通过 CSS 过渡或动画结合 Vue 的动态渲染功能完成。以下是几种常见方法: 使用 Vue 过渡(Transition)组件…

vue搜索实现

vue搜索实现

Vue 搜索功能实现方法 基于计算属性的搜索 在 Vue 中可以通过计算属性实现简单的搜索功能。这种方式适合小型数据集,利用 JavaScript 的 filter 方法进行筛选。 data() {…