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响应式数据的资料请关注脚本之家其它相关文章!

相关文章

  • Vue3 setup的注意点及watch监视属性的六种情况分析

    Vue3 setup的注意点及watch监视属性的六种情况分析

    这篇文章主要介绍了Vue3 setup的注意点及watch监视属性的六种情况,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-04-04
  • Electron进程间通信的实现

    Electron进程间通信的实现

    本文主要介绍了Electron进程间通信的实现,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-05-05
  • Vue实现Tab选项卡切换

    Vue实现Tab选项卡切换

    这篇文章主要为大家详细介绍了Vue实现Tab选项卡切换,点击不同标题显示对应图片,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-09-09
  • vue根据进入的路由进行原路返回的方法

    vue根据进入的路由进行原路返回的方法

    今天小编就为大家分享一篇vue根据进入的路由进行原路返回的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-09-09
  • vue深入解析之render function code详解

    vue深入解析之render function code详解

    vue对大家来说应该再熟悉不过了,下面这篇文章主要给大家深入的解析了vue之render function code的相关资料,文中通过示例代码介绍的非常详细,对大家具有一定的参考学习价值,需要的朋友们下面来一起看看吧。
    2017-07-07
  • Vuejs 用$emit与$on来进行兄弟组件之间的数据传输通信

    Vuejs 用$emit与$on来进行兄弟组件之间的数据传输通信

    本篇文章主要介绍了Vuejs 用$emit 与 $on 来进行兄弟组件之间的数据传输示例,非常具有实用价值,需要的朋友可以参考下。
    2017-02-02
  • vue中el-autocomplete支持分页上拉加载功能

    vue中el-autocomplete支持分页上拉加载功能

    最近在项目中使用了ElementUI的el-autocomplete,下面这篇文章主要介绍了vue中el-autocomplete支持分页上拉加载功能的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2022-11-11
  • vue中@click和@click.native.prevent的区别

    vue中@click和@click.native.prevent的区别

    这篇文章主要介绍了vue中@click和@click.native.prevent的区别,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-04-04
  • VUE引入使用G2图表的实现

    VUE引入使用G2图表的实现

    本文主要介绍了VUE引入使用G2图表的实现,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-08-08
  • Vue表单之v-model绑定下拉列表功能

    Vue表单之v-model绑定下拉列表功能

    这篇文章主要介绍了Vue表单之v-model绑定下拉列表功能,本文通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-05-05

最新评论