vue3.3中ref和reactive原理源代码分析

源码是ts编写的,这里部分简化成js便于阅读

function ref(value) {return createRef(value, false)
}function createRef(rawValue, shallow) { //shallow是否是浅层定义数据,用于区别ref和shallowRefif (isRef(rawValue)) {//如果已经是ref直接返回源数据return rawValue}return new RefImpl(rawValue, shallow)
}class RefImpl<T> {private _value: Tprivate _rawValue: Tpublic dep?: Dep = undefinedpublic readonly __v_isRef = trueconstructor(value: T,//第一个参数value:传入的源数据public readonly __v_isShallow: boolean //第二个参数__v_isShallow:是否是浅层次响应的属性) {this._rawValue = __v_isShallow ? value : toRaw(value)//toRaw是为了防止死循环this._value = __v_isShallow ? value : toReactive(value)//初始化数据如果是已经包装过的__v_isShallow就是true,否则通过toReactive包装传入的参数}get value() {trackRefValue(this) //依赖收集return this._value}set value(newVal) {const useDirectValue = this.__v_isShallow || isShallow(newVal) || isReadonly(newVal)//判断是否已经是vue包装过的对象newVal = useDirectValue ? newVal : toRaw(newVal)if (hasChanged(newVal, this._rawValue)) {this._rawValue = newValthis._value = useDirectValue ? newVal : toReactive(newVal)//如果已经包装过返回源数据,否则通过toReactive包装传入的参数triggerRefValue(this, newVal)//触发响应式更新}}
}toReactive = (value) => isObject(value) ? reactive(value) : value //基本数据类型通过class类依赖收集触发更新,引用数据类型通过Proxy代理实现isObject = (val) => val !== null && typeof val === 'object' //上面用到的函数:判断是否是一个对象//reactive()函数调用createReactiveObject函数(内部通过new Proxy())创建响应式数据,如下:function createReactiveObject(target: Target,isReadonly: boolean,baseHandlers: ProxyHandler<any>,collectionHandlers: ProxyHandler<any>,proxyMap: WeakMap<Target, any>
) {if (!isObject(target)) { //如果不是对象直接返回源数据,所以必须传入对象才有效if (__DEV__) {console.warn(`value cannot be made reactive: ${String(target)}`)}return target}// target is already a Proxy, return it.// exception: calling readonly() on a reactive objectif (target[ReactiveFlags.RAW] &&!(isReadonly && target[ReactiveFlags.IS_REACTIVE])) {return target}// target already has corresponding Proxyconst existingProxy = proxyMap.get(target)if (existingProxy) {return existingProxy}// only specific value types can be observed.const targetType = getTargetType(target)if (targetType === TargetType.INVALID) {return target}const proxy = new Proxy(//创建Proxy代理target,targetType === TargetType.COLLECTION ? collectionHandlers : baseHandlers)proxyMap.set(target, proxy)return proxy
}

总结:

ref() 函数通过调用new RefImpl(rawValue, shallow)这个class类来包装数据,内部有value属性(可读get通过trackRefValue收集依赖;可写set通过triggerRefValue更新依赖), 传入的值会调用toReactive函数进行封装. 
toReactive = (value) => isObject(value) ? reactive(value) : value

isObject = (val) => val !== null && typeof val === 'object'

reactive()函数调用createReactiveObject函数(内部通过new Proxy())创建响应式数据

ref:定义基本数据类型通过class类中的value属性依赖收集触发更新;定义引用数据类型会调用reactive()实现数据代理

reactive:只用于定义引用数据类型,通过Proxy代理实现

附源码地址 https://github.com/vuejs/core/tree/v3.3.4/packages/reactivity/src

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/53372.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Python Flask+Nginx】实现HTTP、WS (两步实现,简单易懂)

目录 一、创建Flask应用 二、部署Nginx 2.1 下载Nginx 2.2 修改Nginx配置文件 2.3 启动Nginx 三、测试 一、创建Flask应用 首先我写了如下一个基于Flask的Demo&#xff0c;该Demo包含两个接口一个是HTTP接口&#xff08;http://127.0.0.1:5000&#xff09;&#xff0c…

Postman如何做接口自动化测试?

前言 什么是自动化测试 把人对软件的测试行为转化为由机器执行测试行为的一种实践。 例如GUI自动化测试&#xff0c;模拟人去操作软件界面&#xff0c;把人从简单重复的劳动中解放出来。 本质是用代码去测试另一段代码&#xff0c;属于一种软件开发工作&#xff0c;已经开发完…

Mybatis多对多查询案例!

在MyBatis中执行多对多查询需要使用两个主要表和一个连接表&#xff08;通常称为关联表&#xff09;来演示。在这个示例中&#xff0c;我们将使用一个示例数据库模型&#xff0c;其中有三个表&#xff1a;students、courses 和 student_courses&#xff0c;它们之间建立了多对多…

RAC sid=‘*‘ 最好加上 v$system_parameter

实验结论&#xff1a;在RAC环境中&#xff0c;最好修改参数sid* 安全可靠&#xff0c;因为暂时未明确知道哪些参数是默认全局修改&#xff0c;什么参数是默认单节点修改的&#xff0c;* 靠谱&#xff0c;不容易出问题 在RAC环境中&#xff0c;修改全局参数scopespfile生效时&am…

sql developer 连不上oracle数据库 报错 ORA-01031: insufficient privileges

sql developer 连不上oracle数据库 报错 ORA-01031: insufficient privileges 1、问题描述2、问题原因3、解决方法4、sql developer 连接oracle 成功 1、问题描述 使用sys账户以SYSDBA角色登录失败 报错 ORA-01031: insufficient privileges 2、问题原因 因为没有给sys账户分…

无涯教程-PHP - Filtered反序列化

PHP 7引入了Filtered unserialize()函数&#xff0c;以在对不受信任的数据上的对象进行反序列化时提供更好的安全性。 <?phpclass MyClass1 { public $obj1prop; }class MyClass2 {public $obj2prop;}$obj1new MyClass1();$obj1->obj1prop1;$obj2new MyClass2();$obj…

Docker-Consul

Docker-Consul 一、介绍1.什么是服务注册与发现2.什么是consul3.consul提供的一些关键特性&#xff1a; 二、consul 部署1.环境准备2.consul服务器3.查看集群信息4.通过 http api 获取集群信息 三、registrator服务器1.安装 Gliderlabs/Registrator2.测试服务发现功能是否正常3…

机器学习简介[01/2]:简单线性回归

Python 中的机器学习简介&#xff1a;简单线性回归 一、说明 简单线性回归为机器学习提供了优雅的介绍。它可用于标识自变量和因变量之间的关系。使用梯度下降&#xff0c;可以训练基本模型以拟合一组点以供未来预测。 二、技术背景 这是涵盖回归、梯度下降、分类和机器学习的其…

MySQL每日一练--校园教务系统

一丶数据库名称&#xff1a;SchoolDB 二丶数据库表信息&#xff1a;角色信息表 表名&#xff1a; t_role 主键&#xff1a; r_id 序号 字段名称 字段说明 类别 位数 属性 备注 1 r_id 角色编号 int 主键 自动增长 2 r_name_EN 角色名&#xff08;英…

学习设计模式之装饰器模式,但是宝可梦

装饰模式 为了不改变组件的结构&#xff0c;动态地扩展其功能。 通常&#xff0c;扩展功能通过子类进行&#xff0c;但是继承的方式具有静态特征&#xff0c;耦合度高。 意图&#xff1a;动态地给对象添加额外的功能 主要解决&#xff1a;继承方式是静态特征&#xff0c;扩…

高效PDF校对:释放高质量内容的力量

在数字化世界中&#xff0c;内容是王者。随着企业和个人越来越依赖数字文档进行沟通、分享和创新&#xff0c;我们在PDF中传递的内容的质量变得至关重要。在这里&#xff0c;我们将探索高效的PDF校对如何帮助您释放高质量内容的真正潜力。 超越仅仅是“正确” 当我们谈论PDF校…

【目标检测】“复制-粘贴 copy-paste” 数据增强实现

文章目录 前言1. 效果展示代码说明3. 参考文档4. 不合适点 前言 本文来源论文《Simple Copy-Paste is a Strong Data Augmentation Method for Instance Segmentation》&#xff08;CVPR2020&#xff09;&#xff0c;对其数据增强方式进行实现。 论文地址&#xff1a;https:/…

[matlab]matlab配置mingw64编译器

第一步&#xff1a;下载官方绿色版本mingw64编译器然后解压放到一个非中文空格路径下面 比如我mingw64-win是我随便改的文件名&#xff0c;然后添加环境变量&#xff0c;选择用户或者系统环境变量添加下面的变量 变量名&#xff1a; MW_MINGW64_LOC 变量值&#xff1a;自己的m…

原生小案例:如何使用HTML5 Canvas构建画板应用程序

使用HTML5 Canvas构建绘图应用是在Web浏览器中创建交互式和动态绘图体验的绝佳方式。HTML5 Canvas元素提供了一个绘图表面&#xff0c;允许您操作像素并以编程方式创建各种形状和图形。本文将为您提供使用HTML5 Canvas创建绘图应用的概述和指导。此外&#xff0c;它还将通过解释…

解决无法远程连接MySQL服务的问题

① 设置MySQL中root用户的权限&#xff1a; [rootnginx-dev etc]# mysql -uroot -pRoot123 mysql> use mysql; mysql> GRANT ALL PRIVILEGES ON *.* TO root% IDENTIFIED BY Root123 WITH GRANT OPTION; mysql> select host,user,authentication_string from user; -…

小小讲一下Linux基本命令

Linux是一套类Unix的操作系统&#xff0c;这套系统最大的优点就是安全便捷&#xff0c;快速高效。这就为它赢得了广大的市场空间。但是呢&#xff0c;Linux系统虽然广为流行&#xff0c;它也不是那么容易就可以学会的。比如说&#xff0c;如果我们不懂得Linux系统的基本操作命令…

【es6】中的Generator

Generator 一、Generator 是什么&#xff1f;1.1 与普通函数写法不一样&#xff0c;有两个不同 二、Generator 使用2.1 书写方法 三、yield语句3.1 yield和return3.2 注意事项3.3 yield*语句3.4 yield*应用 四、next方法4.1参数4.2 运行逻辑 五、异步解决方案六、Generator相关…

Java“牵手”根据关键词搜索(分类搜索)lazada商品列表页面数据获取方法,lazadaAPI实现批量商品数据抓取示例

lazada商城是一个网上购物平台&#xff0c;售卖各类商品&#xff0c;包括服装、鞋类、家居用品、美妆产品、电子产品等。要获取lazada商品列表和商品详情页面数据&#xff0c;您可以通过开放平台的接口或者直接访问lazada商城的网页来获取商品详情信息。以下是两种常用方法的介…

浅析C指针

文章目录 前言指向整型变量的指针指向一维数组的指针以指针为形参且以指针为返回值类型以局部变量地址作为返回值存在的安全隐患 指向字符串的指针通过指针交换两变量的值多级指针指针数组数组指针指向函数的指针 前言 C语言中的指针实质是指向某一对象的内存地址&#xff0c;…

mysql的group by与order by同时使用导致排序

场景描述&#xff1a;接手离职同事的一行代码&#xff0c;如下&#xff1a; select pdtm.name,pdtm.temperature,pdtm.humidity,pdtm.pressure from ( select pp.id,p.name,pp.temperature,pp.humidity,pp.pressure from phe_device_thermo_mst p LEFT JOIN phe_device_thermo…