当前位置:首页 > VUE

vue数据劫持实现

2026-03-07 21:57:44VUE

Vue 数据劫持的实现原理

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

使用 Object.defineProperty

Object.defineProperty 是 Vue 2.x 的核心实现方式,通过劫持对象的属性访问和修改。

vue数据劫持实现

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

const data = {};
defineReactive(data, 'message', 'Hello Vue');
data.message; // 触发 getter
data.message = 'Updated'; // 触发 setter

使用 Proxy

Vue 3.x 改用 Proxy 实现数据劫持,能监听整个对象而非单个属性。

vue数据劫持实现

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

const data = reactive({ message: 'Hello Vue' });
data.message; // 触发 get
data.message = 'Updated'; // 触发 set

嵌套对象的处理

对于嵌套对象,需递归劫持所有属性。

function observe(obj) {
  if (typeof obj !== 'object' || obj === null) return;
  Object.keys(obj).forEach(key => {
    defineReactive(obj, key, obj[key]);
    observe(obj[key]); // 递归劫持嵌套对象
  });
}

const nestedData = { user: { name: 'Vue' } };
observe(nestedData);
nestedData.user.name = 'React'; // 触发嵌套属性的 setter

数组的劫持

数组需特殊处理,重写变异方法(如 pushpop)。

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

function observeArray(arr) {
  arr.__proto__ = arrayMethods;
  arr.forEach(item => observe(item));
}

const arr = [1, 2, 3];
observeArray(arr);
arr.push(4); // 触发自定义 push 方法

总结

  • Vue 2.x 使用 Object.defineProperty 劫持对象属性,需递归处理嵌套对象和数组。
  • Vue 3.x 改用 Proxy 实现更全面的劫持,能直接监听整个对象和数组变化。
  • 数组需通过重写原型方法实现劫持,确保变异方法可被监听。

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

相关文章

vue实现一个tab栏

vue实现一个tab栏

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

vue实现建模

vue实现建模

Vue 实现建模的方法 在 Vue 中实现建模通常涉及数据绑定、组件化和状态管理。以下是几种常见的方法: 数据驱动建模 Vue 的核心是数据驱动视图。通过定义数据模型,Vue 会自动更新 DOM。例…

vue 动画实现

vue 动画实现

Vue 动画实现方式 Vue 提供了多种方式实现动画效果,主要分为内置组件和第三方库集成。 使用 Vue 内置过渡组件 Vue 的 <transition> 和 <transiti…

vue 实现fadeout

vue 实现fadeout

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

vue 实现报价

vue 实现报价

Vue 实现报价功能 在 Vue 中实现报价功能通常涉及前端表单交互、数据计算和与后端 API 的通信。以下是实现报价功能的几种常见方法: 表单设计与数据绑定 使用 Vue 的 v-model 指…

轮播vue实现

轮播vue实现

使用 Vue 实现轮播功能 基础轮播实现 安装依赖(如使用 Swiper): npm install swiper vue-awesome-swiper 组件代码示例: <templ…