当前位置:首页 > VUE

vue数据劫持实现

2026-02-10 22:08:08VUE

Vue 数据劫持实现原理

Vue 的数据劫持主要通过 Object.definePropertyProxy 实现,用于监听数据变化并触发视图更新。

vue数据劫持实现

使用 Object.defineProperty

Object.defineProperty 是 Vue 2.x 的核心实现方式,通过对对象属性的劫持实现响应式。

vue数据劫持实现

function defineReactive(obj, key, val) {
  // 递归处理嵌套对象
  observe(val);

  Object.defineProperty(obj, key, {
    get() {
      console.log(`get ${key}: ${val}`);
      return val;
    },
    set(newVal) {
      if (newVal !== val) {
        console.log(`set ${key}: ${newVal}`);
        observe(newVal); // 处理新值为对象的情况
        val = newVal;
      }
    }
  });
}

function observe(obj) {
  if (typeof obj !== 'object' || obj === null) {
    return;
  }

  Object.keys(obj).forEach(key => {
    defineReactive(obj, key, obj[key]);
  });
}

// 测试
const data = { foo: 'foo', bar: { a: 1 } };
observe(data);
data.foo; // 输出: get foo: foo
data.foo = 'new foo'; // 输出: set foo: new foo
data.bar.a; // 输出: get a: 1

使用 Proxy

Vue 3.x 改用 Proxy 实现,能直接监听整个对象而非属性,且支持数组变化监听。

function reactive(obj) {
  if (typeof obj !== 'object' || obj === null) {
    return obj;
  }

  const observed = new Proxy(obj, {
    get(target, key, receiver) {
      console.log(`get ${key}`);
      const result = Reflect.get(target, key, receiver);
      return reactive(result); // 递归代理嵌套对象
    },
    set(target, key, val, receiver) {
      console.log(`set ${key}: ${val}`);
      return Reflect.set(target, key, val, receiver);
    },
    deleteProperty(target, key) {
      console.log(`delete ${key}`);
      return Reflect.deleteProperty(target, key);
    }
  });

  return observed;
}

// 测试
const data = reactive({ foo: 'foo', bar: { a: 1 } });
data.foo; // 输出: get foo
data.foo = 'new foo'; // 输出: set foo: new foo
data.bar.a; // 输出: get bar -> get a

数组劫持的特殊处理

Vue 2.x 中需重写数组方法(如 pushpop)以实现响应式:

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

['push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse'].forEach(method => {
  const original = arrayProto[method];
  arrayMethods[method] = function(...args) {
    const result = original.apply(this, args);
    console.log(`Array ${method}: ${args}`);
    // 触发更新逻辑
    return result;
  };
});

function observeArray(arr) {
  arr.__proto__ = arrayMethods;
}

// 测试
const arr = [];
observeArray(arr);
arr.push(1); // 输出: Array push: 1

总结

  • Vue 2.x:基于 Object.defineProperty,需递归遍历对象属性,对数组需特殊处理。
  • Vue 3.x:基于 Proxy,可拦截整个对象操作,无需递归初始化,性能更好。

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

相关文章

eventbus vue实现

eventbus vue实现

EventBus 实现原理 EventBus 是一种发布/订阅模式,用于 Vue 组件间的通信。核心是通过一个中央事件总线管理事件监听和触发。 创建 EventBus 在 Vue 项目中创建一个独立…

vue实现管道

vue实现管道

Vue 中实现管道(Pipe)功能 在 Vue 中可以通过过滤器(Filters)或计算属性(Computed Properties)实现类似管道的功能,将数据经过多个处理步骤后输出。 使用过滤器(…

vue实现海报

vue实现海报

Vue 实现海报生成方案 使用 html2canvas 库 html2canvas 是一个将 HTML 元素转换为 Canvas 的库,适合将 Vue 组件渲染为海报图片 安装依赖: npm in…

vue实现快手

vue实现快手

Vue 实现类似快手的功能 Vue.js 是一个渐进式 JavaScript 框架,适合构建复杂的单页应用。要实现类似快手的功能,可以结合 Vue 和相关技术栈进行开发。 核心功能模块 视频流展示…

vue nexttick 实现

vue nexttick 实现

Vue nextTick 实现原理 Vue 的 nextTick 是一个用于在下次 DOM 更新循环结束之后执行延迟回调的方法。它主要用于确保在 DOM 更新完成后执行某些操作。 核心实现机制 ne…

vue  实现关联属性

vue 实现关联属性

Vue 实现关联属性 在 Vue 中实现关联属性通常涉及计算属性(computed properties)或侦听器(watchers),用于根据其他属性的变化动态更新目标属性。 使用计算属性 计算属…