Vue3数据响应式原理

news/2025/1/24 1:33:24/

什么是数据响应式

当数据变化时,引用数据的函数(副作用函数)自动重新执行。
即数据触发了函数的响应,如:视图渲染中使用了某数据,数据改变后,视图跟着自动更新。
触发者:数据
响应者:函数

副作用函数

可以理解为引用了外部数据的函数,这个函数会受到外部数据改变的影响,我们就说这个函数存在副作用。

Vue 3 数据响应式原理

在Vue 2是使用Object.defineProperty()实现响应式。
在Vue 3中,ref是通过Object.defineProperty()来实现响应式,reactive则是通过ES6的Proxy实现响应式的。
通过Proxy构造函数给目标对象创建代理对象,后续对代理对象进行操作,从而实现对目标对象操作(如:读写操作)的拦截和自定义。

const proxy = new Proxy(target,handler)
const target={} // 目标对象
// 定义代理对象
const proxy = new Proxy(target,{get(){},set(){}
})

handler是一个对象,用来定制拦截行为 举个例子
在这里插入图片描述

<!DOCTYPE html>
<html lang="">
<body><div id="app"></div><script>javascript">function reactive(data){return new Proxy(data,{get(target,key,receiver){return Reflect.get(target, key,receiver);},set(target,key,value){const res= Reflect.set(target,key,value);effect();return res;}})}// 定义触发者 数据const state=reactive({message:'hello'});// 定义响应者 副作用函数function effect(){app.innerHTML=state.message;}effect();setTimeout(()=>{state.message='world';},3000)</script>
</body>
</html>

依赖收集

用一个数据结构建立属性和副作用函数的对应关系的过程。
vue3中,在代理对象的get方法中收集依赖,set方法中触发副作用函数重新执行
reactive.js

// 定义一个WeakMap数据结构,保存所有的副作用函数
const targetMap = new WeakMap() 
// 定义全局变量记录当前执行的副作用函数
let activeEffect=null// 创建响应式数据,接受一个普通对象,返回一个代理对象
function reactive(data){return new Proxy(data,{get(target,key,receiver){track(target,key) // get时收集依赖return Reflect.get(target, key,receiver); // 返回值},set(target,key,value){// 赋值const res= Reflect.set(target,key,value);trigger(target,key);  // set时触发副作用函数重新执行return res;}})
}// 注册副作用函数,接受一个副作用函数
function effect(fn){activeEffect=fn // 配置当前执行的副作用函数fn() // 执行副作用函数,会触发get操作,收集依赖activeEffect=null // 重置
}
// 收集依赖的函数 
function track(target,key){if(!activeEffect) return let depMap=targetMap.get(target)if(!depMap){depMap=new Map()targetMap.set(target,depMap)}let depSet=depMap.get(key)if(!depSet){depSet=new Set()depMap.set(key,depSet)}depSet.add(activeEffect)}// 执行副作用函数
function trigger(target,key){const depMap=targetMap.get(target)if(!depMap) returnconst depSet=depMap.get(key)if(!depSet) return// 遍历集合,执行其中的副作用函数depSet.forEach((fn)=>{fn()}) 
}
<!DOCTYPE html>
<html lang="">
<head><meta charset="UTF-8"><script src="./reactive.js"></script>
</head>
<body><script>javascript">// 创建响应式对象const personState=reactive({name:'张三',age:18,gender:'男'});const msgState=reactive({msg:'hello'});// 注册副作用函数effect(function effectName1(){console.log(personState.name)})effect(function effectName2(){console.log(personState.name)})effect(function effectAge(){console.log(personState.age)})effect(function effectMsg(){    console.log(msgState.msg)})setTimeout(()=>{personState.name='李四'},1000)</script>
</body>
</html>

targetMap是一个WeakMap数据结构,WeakMap的key是响应式数据,value是一个Map,Map的key是响应式数据的属性,Map的value是保护着副作用函数的Set
在这里插入图片描述

通过Proxy代理,Vue 3 使用 Proxy 解决了 Vue 2 中的许多局限性。

  • 动态属性添加:解决了Vue 2 无法检测到对象的动态属性添加的问题
  • 数组变更检测:解决了Vue 2 需要手动处理数组的变更的问题
  • 更全面的拦截:Proxy 支持更多类型的拦截操作。

ES6-用Proxy和Reflect操作对象
ES6新增的Set、WeakSet 、Map、WeakMap数据结构
JS对象属性描述符对象和Object.defineProperty()


http://www.ppmy.cn/news/1565641.html

相关文章

【Elasticsearch】inference ingest pipeline

Elasticsearch 的 Ingest Pipeline 功能允许你在数据索引之前对其进行预处理。通过使用 Ingest Pipeline&#xff0c;你可以执行各种数据转换和富化操作&#xff0c;包括使用机器学习模型进行推理&#xff08;inference&#xff09;。这在处理词嵌入、情感分析、图像识别等场景…

IP属地与定位技术:谁更精准地锁定你的位置?

在数字化时代&#xff0c;位置信息的重要性不言而喻。无论是社交媒体上的互动、电商平台的个性化推荐&#xff0c;还是紧急情况下的快速定位&#xff0c;都离不开对位置的准确判断。在众多定位技术中&#xff0c;IP属地与基于GPS等技术的定位服务是最为常见的两种。那么&#x…

使用 Hadoop 实现大数据的高效存储与查询

&#x1f496; 欢迎来到我的博客&#xff01; 非常高兴能在这里与您相遇。在这里&#xff0c;您不仅能获得有趣的技术分享&#xff0c;还能感受到轻松愉快的氛围。无论您是编程新手&#xff0c;还是资深开发者&#xff0c;都能在这里找到属于您的知识宝藏&#xff0c;学习和成长…

【MySQL】超详细MySQL常用日期格式转换函数、字符串函数、聚合函数(最新版)

文章目录 一、MySQL常用日期格式转换函数 1、查看当前日期时间2、日期函数3、日期格式转换4、字符串日期转换5、时间单位转换6、DATE_ADD(date,interval expr type) 从日期加上指定的时间间隔 [expr为正数是往后加&#xff0c;为负数是往前减]7、DATE_SUB(date,interval expr …

自定义BeanPostProcessor实现自动注入标注了特定注解的Bean

定义注解 Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD}) Retention(RetentionPolicy.RUNTIME) Documented public interface MyAnno { }定义一个配置类 Configuration public class RestConfig {MyAnnoBeanpublic PayDTO payDTO(){PayDTO payDTO …

三篇物联网漏洞挖掘综述

由于物联网设备存在硬件资源受限、硬件复杂异构&#xff0c; 代码、文档未公开的问题&#xff0c; 物联网设备的漏洞挖掘存在较大的挑战&#xff1a; 硬件资源受限性: 通用动态二进分析技术需要在运行程序外围实施监控分析。由于物联网设备存储资源(存储)的受限性&#xff0c;…

win32汇编环境,怎么得到磁盘的盘符

;运行效果 ;win32汇编环境,怎么得到磁盘的盘符 ;以下代码主要为了展示一下原理&#xff0c;应用GetLogicalDrives、GetLogicalDriveStrings函数、屏蔽某些二进制位、按双字节复制内容等。以下代码最多查8个盘&#xff0c;即返回值中的1个字节的信息 ;直接抄进RadAsm可编译运行。…

【Rust自学】14.3. 使用pub use导出方便使用的API

喜欢的话别忘了点赞、收藏加关注哦&#xff08;加关注即可阅读全文&#xff09;&#xff0c;对接下来的教程有兴趣的可以关注专栏。谢谢喵&#xff01;(&#xff65;ω&#xff65;) 14.3.1. 使用pub use导出方便使用的API 在第七章中我们介绍了mod关键字&#xff0c;我们使…