当前位置:首页 > VUE

vue数据拦截怎么实现

2026-01-23 12:36:23VUE

Vue 数据拦截的实现方式

Vue 的数据拦截核心是通过 Object.definePropertyProxy 实现的响应式系统,以下是具体实现方法:

vue数据拦截怎么实现

使用 Object.defineProperty(Vue 2.x)

通过劫持对象的属性访问和修改,触发依赖收集和更新通知。

vue数据拦截怎么实现

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

  Object.defineProperty(obj, key, {
    get() {
      console.log(`读取 ${key}: ${val}`);
      return val;
    },
    set(newVal) {
      if (newVal !== val) {
        console.log(`设置 ${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: 'bar' };
observe(data);
data.foo; // 输出 "读取 foo: bar"
data.foo = 'baz'; // 输出 "设置 foo 为 baz"

使用 Proxy(Vue 3.x)

通过代理对象拦截所有属性的操作,支持数组和动态新增属性。

function reactive(obj) {
  return new Proxy(obj, {
    get(target, key) {
      console.log(`读取 ${key}: ${target[key]}`);
      return target[key];
    },
    set(target, key, val) {
      if (target[key] !== val) {
        console.log(`设置 ${key} 为 ${val}`);
        target[key] = val;
      }
      return true;
    }
  });
}

// 测试
const data = reactive({ foo: 'bar' });
data.foo; // 输出 "读取 foo: bar"
data.foo = 'baz'; // 输出 "设置 foo 为 baz"

实现依赖收集与更新

结合发布-订阅模式,在拦截时触发依赖更新:

class Dep {
  constructor() {
    this.subscribers = new Set();
  }
  depend() {
    if (activeEffect) this.subscribers.add(activeEffect);
  }
  notify() {
    this.subscribers.forEach(effect => effect());
  }
}

let activeEffect = null;
function watchEffect(effect) {
  activeEffect = effect;
  effect();
  activeEffect = null;
}

// 修改 defineReactive 加入依赖收集
function defineReactive(obj, key, val) {
  const dep = new Dep();
  observe(val);
  Object.defineProperty(obj, key, {
    get() {
      dep.depend();
      return val;
    },
    set(newVal) {
      if (newVal !== val) {
        observe(newVal);
        val = newVal;
        dep.notify();
      }
    }
  });
}

// 测试
const data = { count: 0 };
observe(data);
watchEffect(() => {
  console.log(`当前计数: ${data.count}`);
});
data.count++; // 触发日志输出

注意事项

  1. 性能问题Object.defineProperty 需要递归遍历对象,初始化性能较差。
  2. 数组限制:Vue 2.x 需重写数组方法(如 push)实现拦截。
  3. Proxy 优势:Vue 3.x 的 Proxy 直接支持动态属性和数组操作。

通过上述方法可以实现类似 Vue 的响应式数据拦截,核心在于在数据访问时收集依赖,在数据变更时触发更新。

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

相关文章

vue实现图片分析

vue实现图片分析

Vue 实现图片分析的方法 在 Vue 中实现图片分析通常涉及图片上传、预览、后端交互以及分析结果展示等功能。以下是几种常见的实现方式: 使用 HTML5 File API 和 Canvas…

vue实现点击旋转轮盘

vue实现点击旋转轮盘

实现点击旋转轮盘效果 在Vue中实现点击旋转轮盘效果,可以通过CSS动画和Vue的数据绑定结合完成。以下是一个完整的实现方案: 准备工作 需要安装Vue.js环境,可以通过CDN引入或使用Vue C…

vue实现alert

vue实现alert

实现自定义 Alert 组件 在 Vue 中可以通过组件化方式实现自定义 Alert 弹窗。以下是基于 Vue 3 的实现示例: 组件代码 (Alert.vue) <template>…

vue实现高亮

vue实现高亮

Vue 实现文本高亮的方法 在 Vue 中实现文本高亮可以通过多种方式完成,以下是几种常见的方法: 方法一:使用 v-html 指令 通过 v-html 指令可以动态插入 HTML 内容,将需要高…

简单实现vue

简单实现vue

Vue 的基本实现 创建一个简单的 Vue 应用需要引入 Vue 库,并编写基本的模板和数据绑定逻辑。 <!DOCTYPE html> <html lang="en"> &…

vue实现公告

vue实现公告

Vue 实现公告功能的方法 公告功能通常需要实现滚动展示、自动切换或固定显示的效果。以下是几种常见的实现方式: 使用 marquee 标签实现滚动公告 <template> <…