当前位置:首页 > VUE

vue实现数据劫持

2026-01-18 09:46:50VUE

Vue 数据劫持的实现原理

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

使用 Object.defineProperty

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

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} 从 ${val} 到 ${newVal}`);
      val = newVal;
    }
  });
}

const data = { name: 'Vue' };
defineReactive(data, 'name', data.name);
data.name; // 输出: "获取属性 name: Vue"
data.name = 'React'; // 输出: "设置属性 name 从 Vue 到 React"

使用 Proxy

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

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} 从 ${target[key]} 到 ${value}`);
      target[key] = value;
      return true;
    }
  });
}

const data = reactive({ name: 'Vue' });
data.name; // 输出: "获取属性 name: Vue"
data.name = 'React'; // 输出: "设置属性 name 从 Vue 到 React"

深度监听

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

Object.defineProperty 实现

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

const data = { user: { name: 'Alice' } };
observe(data);
data.user.name = 'Bob'; // 触发 setter

Proxy 实现

function deepReactive(obj) {
  if (typeof obj !== 'object' || obj === null) return obj;
  Object.keys(obj).forEach(key => {
    obj[key] = deepReactive(obj[key]); // 递归处理嵌套属性
  });
  return reactive(obj);
}

const data = deepReactive({ user: { name: 'Alice' } });
data.user.name = 'Bob'; // 触发 setter

数组的劫持

Vue 2.x 中需特殊处理数组方法(如 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);
  };
});

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

const list = [1, 2, 3];
observeArray(list);
list.push(4); // 输出: "数组方法 push 被调用"

注意事项

  • Object.defineProperty 无法检测新增或删除的属性,需使用 Vue.setVue.delete
  • Proxy 能直接监听新增/删除属性,但需注意浏览器兼容性(IE 不支持)。
  • 性能上 Proxy 优于递归 defineProperty,尤其对复杂对象结构。

vue实现数据劫持

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

相关文章

vue实现自动翻译

vue实现自动翻译

Vue 实现自动翻译的方法 在 Vue 项目中实现自动翻译功能可以通过多种方式完成,以下是几种常见的方法: 使用第三方翻译 API 注册并获取翻译 API 的密钥(如 Google Translat…

vue实现矩阵

vue实现矩阵

Vue 实现矩阵的方法 在 Vue 中实现矩阵操作可以通过多种方式完成,以下是一些常见的方法: 使用二维数组表示矩阵 矩阵可以用二维数组来表示,每个元素对应矩阵中的一个值。在 Vue 的 data…

vue实现store

vue实现store

Vue 实现 Store 在 Vue 中,可以通过 Vuex 或 Pinia 实现全局状态管理(Store)。以下是两种主流方案的实现方法。 使用 Vuex 实现 Store Vuex 是 Vue…

vue实现muli

vue实现muli

Vue 实现多语言(i18n)支持 在 Vue 项目中实现多语言(i18n)功能,通常使用 vue-i18n 插件。以下是具体实现步骤: 安装 vue-i18n npm install vue-i…

vue实现管道

vue实现管道

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

vue多选实现

vue多选实现

Vue 多选实现方法 基础实现(v-model + multiple) 在 Vue 中实现多选可以通过 <select> 元素的 multiple 属性结合 v-model 完成。v-mo…