当前位置:首页 > 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实现预览

Vue实现文件预览的方法 使用Vue实现文件预览功能可以通过多种方式完成,具体取决于文件类型(图片、PDF、视频等)。以下是几种常见文件类型的实现方案。 图片预览 通过<input type…

vue实现购物按钮

vue实现购物按钮

Vue 购物按钮实现方法 基础按钮实现 使用 Vue 的模板语法创建基础按钮组件,绑定点击事件处理购物逻辑: <template> <button @click="addToC…

vue弹幕实现不重叠

vue弹幕实现不重叠

实现 Vue 弹幕不重叠的方法 CSS 定位与动画控制 通过绝对定位和动态计算弹幕轨道高度,确保弹幕在不同轨道上运行。每条弹幕占据固定高度的轨道,避免重叠。 // 弹幕轨道高度计算 const tr…

vue实现冰墩墩

vue实现冰墩墩

使用 Vue 实现冰墩墩动画 通过 Vue 的动画特性和 SVG 技术,可以动态渲染冰墩墩的形象。以下是具体实现方法: 准备 SVG 素材 冰墩墩的形象通常由多个 SVG 路径组成,包括身体轮廓、面…

vue实现视频会议

vue实现视频会议

使用 Vue 实现视频会议 技术选型 Vue.js 作为前端框架,结合 WebRTC 技术实现实时音视频通信。常用的库包括: peerjs:简化 WebRTC 的点对点连接。 socket.io:用…

vue实现多选题

vue实现多选题

Vue实现多选题的方法 使用Vue实现多选题功能,可以通过v-model绑定数组、动态渲染选项、以及处理选中状态来实现。以下是一个完整的实现示例: 基础实现代码 <template>…