当前位置: 首页 > news >正文

Vue3响应式原理

Vue 3 的响应式系统基于 Proxy 对象实现,具有更高的性能和灵活性,相比 Vue 2 使用的 Object.defineProperty 有明显的改进。以下是 Vue 3 响应式原理的关键部分:


1. 核心机制

Vue 3 响应式系统的核心是 reactive API,它使用 Proxy 拦截对对象的访问和修改,从而实现数据的追踪和更新。

1.1 reactive 的实现
import { reactive } from 'vue';const state = reactive({count: 0,info: {name: 'Vue',version: 3}
});

在上述代码中:

  • reactive 会将传入的普通对象转换为响应式对象。
  • Vue 通过 Proxy 拦截对对象的操作(如 getset),从而实现依赖收集和变化通知。

1.2 依赖收集与追踪

响应式系统的工作过程可以分为以下几步:

  1. 依赖收集:当某个响应式属性被访问时,Vue 会记录哪个组件或函数依赖了该属性。
  2. 触发更新:当响应式属性的值发生变化时,Vue 通知所有依赖该属性的函数重新执行。

依赖收集是通过 Effect 函数 实现的:

import { effect } from 'vue';effect(() => {console.log(state.count);
});

在执行 effect 时,Vue 会自动订阅 state.count,因此当 state.count 的值发生变化时,该 effect 会重新运行。


2. Proxy 的核心拦截点

Vue 3 的响应式系统通过 Proxy 提供的拦截机制,完成以下操作:

2.1 get:读取属性

当访问对象的属性时,Vue 会触发 get 拦截器,从而完成依赖收集:

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

当修改对象的属性时,Vue 会触发 set 拦截器,从而通知依赖更新:

const handler = {set(target, key, value, receiver) {const result = Reflect.set(target, key, value, receiver);console.log(`设置属性 ${key}: ${value}`);// 触发依赖更新return result;}
};
2.3 tracktrigger

Vue 3 将依赖追踪和触发分成了两个步骤:

  • track:在 get 中调用,用于记录依赖。
  • trigger:在 set 中调用,用于通知依赖更新。

3. 响应式工具

Vue 3 提供了一些内置工具和方法,帮助开发者处理响应式对象。

3.1 reactiveref
  • reactive:将对象或数组转换为响应式对象。
  • ref:用于包装单个值,使其具有响应式能力。
import { ref } from 'vue';const count = ref(0);effect(() => {console.log(count.value); // 监听 count 的变化
});
count.value++; // 触发更新
3.2 computed
  • computed 用于创建基于响应式数据的派生状态,并具有缓存功能。
import { computed } from 'vue';const doubled = computed(() => count.value * 2);
console.log(doubled.value); // 自动计算并缓存结果

4. 与 Vue 2 的对比

特性Vue 2 (Object.defineProperty)Vue 3 (Proxy)
支持的数据类型仅支持对象和数组支持对象、数组、Map、Set 等多种类型
深度响应式初始化时递归遍历对象按需追踪,性能更优
新增/删除属性响应式需要 Vue.setVue.delete原生支持
性能初始化开销较大,动态追踪效率低初始化开销小,动态追踪效率高

5. 总结

Vue 3 的响应式系统使用 Proxy 和优化的依赖追踪机制(tracktrigger),实现了:

  1. 更灵活的响应式能力(支持 Map、Set 等)。
  2. 更高的性能(按需追踪,避免冗余计算)。
  3. 更简洁的 API(无需手动处理新增/删除属性)。

http://www.mrgr.cn/news/77952.html

相关文章:

  • python中如何使用指数
  • 量子卷积神经网络
  • 利用c语言详细介绍下插入排序
  • RK356x-10:串口(uart)配置与调试
  • Webpack之后,Rollup如何引领前端打包新潮流?(1)
  • 对比 MyBatis 批处理 BATCH 模式与 INSERT INTO ... SELECT ... UNION ALL 进行批量插入
  • Springboot项目搭建-Maven打包编译
  • 演示如何使用 `nn.CrossEntropyLoss` 来计算交叉熵损失,计算损失值的演示代码,和讲解 ,CrossEntropyLoss 损失数值等于零的原因
  • hugo文章支持数学公式
  • oracle 12c查看执行过的sql及当前正在执行的sql
  • 【计算机网络】多路转接之select
  • 新华三嵌入式面试题及参考答案
  • 海信Java后端开发面试题及参考答案
  • 第三十九篇 ShuffleNet V1、V2模型解析
  • Optional类
  • Leetcode 51 N Queens
  • 高频面试题(含笔试高频算法整理)基本总结回顾16
  • pinia的使用
  • 【c++篇】掌握动态内存的奥妙
  • Modern Effective C++ item 15:尽可能的使用constexpr
  • 活着就好20241125
  • 禁用达梦DEM的agent
  • 大数取模 详解
  • 【数据库原理】创建与维护表,DDL数据定义语言
  • Java项目实战II基于SpringBoot的教学资料管理系统(开发文档+数据库+源码)
  • 交叉熵 vs focal loss