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

    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,可直接监听对象和数组的变化,无需递归或重写方法。

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 方法中,通知所有依赖进行更新。

    vue数据劫持实现

    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实现选区

Vue 实现选区的基本方法 在Vue中实现选区功能通常涉及DOM操作和事件处理。以下是几种常见的方法: 使用原生JavaScript的Selection API 通过window.getSelec…

vue实现批量

vue实现批量

Vue 实现批量操作的方法 在 Vue 中实现批量操作通常涉及选择多个项目并执行统一处理,例如批量删除、批量更新等。以下是几种常见实现方式: 表格多选批量操作 使用 el-table 配合复选框实现…

vue实现排序

vue实现排序

Vue 实现排序的方法 在 Vue 中实现排序可以通过多种方式完成,以下是一些常见的方法: 使用计算属性排序数组 计算属性非常适合对数据进行排序,因为它会在依赖的数据变化时自动更新。以下是一个示例:…

vue实现素材

vue实现素材

Vue 实现素材的方法 使用 Vue 组件管理素材 在 Vue 项目中,可以通过组件化的方式管理素材。创建一个专门的组件来加载和显示素材,例如图片、视频或音频文件。组件可以接收素材的路径或 URL 作…

vue 实现表单

vue 实现表单

Vue 表单实现方法 Vue.js 提供了多种方式实现表单,包括双向数据绑定、表单验证和动态表单生成。以下是常见的实现方法: 基础表单绑定 使用 v-model 指令实现表单元素与数据的双向绑定:…

vue代理实现

vue代理实现

Vue 代理实现方法 在 Vue 项目中,配置代理可以解决开发环境下的跨域问题,通常通过修改 vue.config.js 文件实现。以下是几种常见的代理配置方式: 基础代理配置 在 vue.conf…