Vue3使用Proxy构建高效响应式数据的示例代码

 更新时间:2025年03月04日 08:51:23   作者:奇舞精选  
在 Vue 3 中,Proxy 主要用于 拦截对象的基本操作,包括 属性读取(get)、修改(set)、删除(deleteProperty) 等,本文给大家介绍了Vue3使用Proxy构建高效响应式数据的操作教程,需要的朋友可以参考下

Proxy 的核心机制

在 Vue 3 中,Proxy 主要用于 拦截对象的基本操作,包括 属性读取(get)、修改(set)、删除(deleteProperty) 等。这是 Vue 3 取代 Object.defineProperty 的根本原因。

Proxy 允许拦截的操作:

操作作用
get(target, key, receiver)读取属性时触发
set(target, key, value, receiver)设置属性时触发
deleteProperty(target, key)删除属性时触发
has(target, key)判断 key 是否存在(key in obj)
ownKeys(target)获取对象的所有键(Object.keys(obj))
apply(target, thisArg, args)代理函数调用
construct(target, args)代理 new 操作符

Proxy 的核心实现

让我们通过一个 手写 Proxy 劫持 的例子,模拟 Vue 3 响应式数据的基本实现:

const handler = {
  get(target, key) {
    console.log(`读取属性:${key}`);
    return Reflect.get(target, key);
  },
  set(target, key, value) {
    console.log(`修改属性:${key} -> ${value}`);
    return Reflect.set(target, key, value);
  }
};

const data = { message: "Hello Vue 3" };
const proxyData = new Proxy(data, handler);

console.log(proxyData.message); // 读取属性:message
proxyData.message = "Updated"; // 修改属性:message -> Updated

解读:

​ • Reflect.get(target, key):用于获取目标对象的值,等价于 target[key]。

​ • Reflect.set(target, key, value):用于修改目标对象的值,等价于 target[key] = value。

​ • Vue 3 就是基于 Proxy 设计 reactive() 来创建响应式数据。

Vue 3 如何基于 Proxy 构建响应式系统

Vue 3 的核心响应式 API reactive() 就是对 Proxy 的封装,具体实现如下:

function reactive(target) {
  if (typeof target !== "object" || target === null) {
    return target;
  }

  return new Proxy(target, {
    get(target, key, receiver) {
      console.log(`访问属性:${key}`);
      return Reflect.get(target, key, receiver);
    },
    set(target, key, value, receiver) {
      console.log(`修改属性:${key} -> ${value}`);
      return Reflect.set(target, key, value, receiver);
    }
  });
}

const state = reactive({ count: 0 });

console.log(state.count); // 访问属性:count
state.count++; // 修改属性:count -> 1

Vue 3 reactive() 实现的核心点

​ 1. 使用 Proxy 劫持整个对象,而不是每个属性

​ 2. 支持深层次代理(但 Vue 3 默认是惰性代理,访问时才创建嵌套对象的代理)。

​ 3. 拦截数组和对象的方法(如 push、pop、delete)

Vue 3 的依赖收集与副作用处理机制

Vue 3 采用 “响应式依赖收集 + 依赖触发” 来完成视图更新,核心组件包括:

​ • reactive():创建响应式数据(基于 Proxy)。

​ • effect():收集依赖,记录哪些属性被访问。

​ • trigger():数据变更时通知所有依赖执行。

1. Vue 3 依赖收集的核心实现

let activeEffect = null; // 当前正在执行的 effect
const targetMap = new WeakMap(); // 存储依赖

function effect(fn) {
  activeEffect = fn;
  fn(); // 立即执行一次,收集依赖
  activeEffect = null;
}

function track(target, key) {
  if (activeEffect) {
    let depsMap = targetMap.get(target);
    if (!depsMap) {
      depsMap = new Map();
      targetMap.set(target, depsMap);
    }
    let deps = depsMap.get(key);
    if (!deps) {
      deps = new Set();
      depsMap.set(key, deps);
    }
    deps.add(activeEffect);
  }
}

function trigger(target, key) {
  const depsMap = targetMap.get(target);
  if (!depsMap) return;
  const effects = depsMap.get(key);
  if (effects) {
    effects.forEach(fn => fn()); // 触发所有依赖
  }
}

// 结合 Proxy 创建 Vue 3 响应式对象
function reactive(target) {
  return new Proxy(target, {
    get(target, key, receiver) {
      track(target, key); // 依赖收集
      return Reflect.get(target, key, receiver);
    },
    set(target, key, value, receiver) {
      const result = Reflect.set(target, key, value, receiver);
      trigger(target, key); // 触发更新
      return result;
    }
  });
}

2. Vue 3 响应式数据的完整示例

const state = reactive({ count: 0 });

effect(() => {
  console.log(`count 更新:${state.count}`);
});

state.count++; // 触发更新:count 更新:1
state.count = 5; // 触发更新:count 更新:5

执行流程:

​ 1. effect(() => console.log(state.count)) 执行时,触发 get(),收集 state.count 的依赖。

​ 2. state.count++ 触发 set(),调用 trigger() 通知所有依赖执行 effect()。

Vue 3 Proxy 响应式系统的优化

1. 依赖按需收集

Vue 2 在初始化时遍历整个对象,而 Vue 3 只有在 访问属性时才进行代理,减少性能消耗。

2. 自动清理无效依赖

Vue 3 采用 WeakMap + Set 进行依赖存储,避免内存泄漏,Vue 2 需要手动管理依赖删除。

3. 只更新受影响的组件

Vue 3 的 trigger() 机制让每个组件只更新它所依赖的部分,避免 Vue 2 中全局重新计算的问题。

总结

Proxy 使 Vue 3 的响应式系统更高效,支持新增属性监听、数组操作拦截等。依赖追踪采用 WeakMap + Set 存储,提高性能,避免 Vue 2 的内存泄漏问题。 Vue 3 采用 Lazy Proxy(惰性代理),只有访问属性时才进行代理,减少初始化开销。Vue 3 的响应式机制通过effect() 进行自动依赖收集,让数据更新更智能、更高效。

以上就是Vue3使用Proxy构建高效响应式数据的示例代码的详细内容,更多关于Vue3 Proxy响应式数据的资料请关注脚本之家其它相关文章!

相关文章

  • 在vue中使用echarts图表实例代码详解

    在vue中使用echarts图表实例代码详解

    本文通过实例代码给大家介绍了在vue中使用echarts图表的方法,需要注意的事项文中给大家提到,需要的朋友可以参考下
    2018-10-10
  • Vue文件下载进度条的实现过程

    Vue文件下载进度条的实现过程

    这篇文章主要介绍了Vue文件下载进度条的实现原理,通过使用onDownloadProgress方法API获取进度及文件大小等数据,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-07-07
  • Vue2+SpringBoot实现数据导出到csv文件并下载的使用示例

    Vue2+SpringBoot实现数据导出到csv文件并下载的使用示例

    本文主要介绍了Vue2+SpringBoot实现数据导出到csv文件并下载,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-10-10
  • vue+webpack模拟后台数据的示例代码

    vue+webpack模拟后台数据的示例代码

    这篇文章主要介绍了vue+webpack模拟后台数据的示例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-07-07
  • 基于vue实现一个神奇的动态按钮效果

    基于vue实现一个神奇的动态按钮效果

    今天我们将利用vue的条件指令来完成一个简易的动态变色功能按钮,本文通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友参考下吧
    2019-05-05
  • 导致VUE页面不刷新的问题分析及解决方法

    导致VUE页面不刷新的问题分析及解决方法

    由于 Vue 会在初始化实例时对 property 执行 getter/setter 转化,所以 property 必须在 data 对象上存在才能让 Vue 将它转换为响应式的,这篇文章主要介绍了导致VUE页面不刷新的问题分析及解决方法,需要的朋友可以参考下
    2024-04-04
  • Vue设置select下拉框的默认选项详解(select空白bug解决)

    Vue设置select下拉框的默认选项详解(select空白bug解决)

    最近开始学习vue,在学习的过程中遇到的问题将记录在这里,下面这篇文章主要给大家介绍了关于Vue设置select下拉框的默认选项(select空白bug解决)的相关资料,需要的朋友可以参考下
    2022-12-12
  • VUE 实现一个简易老虎机的项目实践

    VUE 实现一个简易老虎机的项目实践

    老虎机在很多地方都可以见到,可以设置中奖位置,以及中奖回调,本文主要介绍了VUE 实现一个简易老虎机的项目实践,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-04-04
  • 对Vue table 动态表格td可编辑的方法详解

    对Vue table 动态表格td可编辑的方法详解

    今天小编就为大家分享一篇对Vue table 动态表格td可编辑的方法详解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-08-08
  • vue实现input框禁止输入标签

    vue实现input框禁止输入标签

    这篇文章主要介绍了vue实现input框禁止输入标签,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-04-04

最新评论