当前位置:首页 > VUE

vue数据劫持实现

2026-01-14 05:23:10VUE

Vue 数据劫持实现原理

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

基于 Object.defineProperty

  1. 劫持对象属性 通过 Object.defineProperty 重写对象的 getset 方法,在属性被访问或修改时触发依赖收集和更新通知。

    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);
  2. 递归劫持嵌套对象 需要递归处理对象中的嵌套属性,确保所有层级的数据均可被监听。

    vue数据劫持实现

    function observe(obj) {
      if (typeof obj !== 'object' || obj === null) return;
      Object.keys(obj).forEach(key => {
        defineReactive(obj, key, obj[key]);
        observe(obj[key]); // 递归处理嵌套对象
      });
    }
  3. 数组方法劫持 由于 Object.defineProperty 无法直接监听数组变化,需重写数组的变异方法(如 pushpop)。

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

基于 Proxy(Vue 3)

Vue 3 使用 Proxy 替代 Object.defineProperty,可直接监听对象和数组的变化,无需递归或重写方法。

vue数据劫持实现

function reactive(obj) {
  return new Proxy(obj, {
    get(target, key) {
      console.log(`读取属性 ${key}`);
      return Reflect.get(target, key);
    },
    set(target, key, val) {
      if (target[key] === val) return true;
      console.log(`更新属性 ${key},新值: ${val}`);
      return Reflect.set(target, key, val);
    }
  });
}

const data = reactive({ name: 'Vue 3' });

依赖收集与派发更新

  1. 依赖收集get 方法中,将当前属性的依赖(如 Watcher)存储到全局的依赖收集器(Dep)中。

    class Dep {
      constructor() {
        this.subscribers = new Set();
      }
      depend() {
        if (activeEffect) this.subscribers.add(activeEffect);
      }
      notify() {
        this.subscribers.forEach(effect => effect());
      }
    }
  2. 派发更新set 方法中,通知所有依赖进行更新。

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

总结

  • Vue 2:通过 Object.defineProperty 递归劫持对象属性,重写数组方法实现监听。
  • Vue 3:使用 Proxy 直接代理对象,简化监听逻辑,性能更优。
  • 依赖收集和派发更新机制确保数据变化时视图自动同步。

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

相关文章

vue实现文件下载

vue实现文件下载

使用 a 标签下载文件 通过动态创建 a 标签并触发点击事件实现文件下载。适用于直接下载服务器上的静态文件或 Blob 数据。 downloadFile(url, fileName) {…

vue实现静态查询

vue实现静态查询

Vue 实现静态查询 在 Vue 中实现静态查询通常指不依赖后端接口,直接在前端处理数据筛选或搜索功能。以下是几种常见实现方式: 使用计算属性过滤数据 通过计算属性对静态数据进行筛选,适合简单查询场…

vue实现图片分析

vue实现图片分析

Vue 实现图片分析的方法 在 Vue 中实现图片分析通常涉及图片上传、预览、后端交互以及分析结果展示等功能。以下是几种常见的实现方式: 使用 HTML5 File API 和 Canvas 进行…

vue怎么实现动画

vue怎么实现动画

Vue 动画实现方法 Vue 提供了多种方式实现动画效果,包括内置过渡系统、第三方库集成以及 CSS 动画。以下是常见实现方法: 使用 Vue 过渡系统 通过 <transition>…

vue实现表格数据修改

vue实现表格数据修改

实现表格数据修改的基本思路 在Vue中实现表格数据的修改通常涉及以下核心步骤:数据绑定、事件监听、状态管理。通过双向绑定(v-model)或手动更新数据的方式实现动态编辑功能。 基础实现方法 数据准…

vue数据代理底层实现

vue数据代理底层实现

Vue数据代理的底层实现原理 Vue的数据代理是通过Object.defineProperty或Proxy实现的,主要目的是让开发者能够直接通过实例访问data中的属性,而不需要写data.xxx的形…