【Vue3源码实现】Ref isRef unRef proxyRefs实现

前言

在上篇文章中 我们了解了响应式原理,并在最后实现了reactive。
上文链接🔥🔥🔥Vue3响应式原理实现与track和trigger依赖收集和触发依赖
在我们的日常业务中,我们有可能需要将一个基础数据类型的值也转换成响应式的,而reactive只能代理对象,我们需要对基础数据类型的值也进行读写操作的拦截,但 Proxy 无法实现对基础数据类型值读写操作的拦截。
所以Vue设计了Ref,以及相关api
本篇文章实现下Ref及相关API isRef ,unRef,proxyRefs

先来列举下实现ref需要注意的几点

ref在script标签中必须.value才能使用 在template标签中则不用
ref既能代理原始数据,又能代理对象数据,还可以同时代理原始数据与对象数据,
如果参数是一个对象的话,ref的内部会使用 reactive 对参数进行一层转化封装

先实现下它.value这个东西,在vue源码中是将ref的值包裹在一个RefImp类中实现的

class RefImp {private _value: any;constructor(value) {// 判断 value 值是不是对象,如果是对象,则用 reactive 包裹this._value = isObject(value) ? reactive(value) : value;}get value() {// 直接返回 _valuereturn this._value;}set value(value) {// 设置 _valuethis._value = value;}}function ref(value) {return new RefImp(value);}
//试验一波
const obj = { a: 1 };
const refObj = ref(obj); console.log(refObj.value); // 输出: { a: 1 }
接下来实现ref的响应式
export class RefImp {
private _value: any;
public dep: any;
constructor(value) {
// / 看看value 是不是一个对象,如果是一个对象的话则转为响应式对象this._value = isObject(value) ? reactive(value) : value
this.dep = new Set()
}
get value() {
TrackEffects(this.dep)
return this._value
}
set value(newvalue) {
// 检查新值是否发生变化
if (!Object.is(newvalue,_value)) {
this._value = isObject(newValue) ? reactive(newValue) : newValue
TriggerEffect(this.dep)
}
}
}
// `TrackEffects` 函数用于追踪依赖关系,而 `TriggerEffect` 函数用于触发相关效果。
//这是从track和trigger中抽离出来的
function TrackEffects(dep: any) {
if (!dep.has(activeEffect)) {dep.add(activeEffect)activeEffect.deps.push(dep)
}
}
export function TriggerEffect(dep) {
for (const effect of dep) {
effect.run()
}
}

优化下代码,因为_value可能被reactive修改为Proxy对象,

新传入的值不可能相等,所以需要有个rawValue存储原来的传入的value与newValue对比

export class RefImp {
...
private rawValue: any;
...
constructor(value) {
this.rawValue = value
...
}
set value(newValue){if(!Object.is(newValue,this.rawValue)){this.rawValue = newValuethis._value = isObject(newValue) ? reactive(newValue) : newValue...}
}
}

isRef

检查某个值是否为 ref。我们可以在refImp类中加入属性来判断

class refImp{
public _v_isRef = true;
...
}
function isRef(value){return !!value._v_isRef
}

unRef

如果参数是 ref对象,则返回内部值,否则返回参数本身。

function(value){return isRef(value) ? value.value : value 
}

proxyRefs

前言我们说到有一点 为什么template中不需要.value,
因为Vue使用 proxyRefs 来处理响应式引用的模板解析。proxyRefs 是一个内部函数,用于处理模板中的响应式引用。它会将传入的响应式引用对象转换为代理对象,从而在模板中直接访问引用的属性时能够自动获取其 value 属性的值
接下来实现它

export function proxyRefs(objectWithRefs) {return new Proxy(objectWithRefs, {get(target, key) {return unRef(Reflect.get(target, key))},set(target, key, value) {if (isRef(target[key]) && !isRef(value)) {return target[key].value = value} else {return Reflect.set(target, key, value)}}})}

文章到这里就结束了,希望对你有所帮助。

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

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

相关文章

Linux 生态与工具

各位大佬好 ,这里是阿川的博客 , 祝您变得更强 个人主页:在线OJ的阿川 大佬的支持和鼓励,将是我成长路上最大的动力 阿川水平有限,如有错误,欢迎大佬指正 目录 Linux生态简介:Linux工具lrzsz&#xff…

抖音产品全线恢复

商城,商品,直播,小黄车 等等

mysql数据库插入中文失败

有一张表,结构如下: MariaDB [test]> show create table dept; ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------…

智能仪表在铁塔行业的应用

应用场景 可应用于基站的交直流配电箱及对基站内的动力设备进行数据采集和控制。 功能 1.对多个回路进行全电参量测量,实现基站内各回路用电能耗的集中管理; 2.丰富的DI/DO输入输出,NTC测温,温湿度测量等非电参量监测&#xff…

分体工业读写器的适用场景有哪些?

工业读写器根据设计方式不同,可分为一体式读写器和分体式读写器,不同读写器特点不同,适用场景也不同,下面我们就一起来了解一下超高频分体读写器适用场景有哪些。 超高频分体读写器介绍 超高频分体读写器是一种射频识别(RFID)设…

Sass语法介绍-导入

11【Sass语法介绍-导入】 1.前言 在 CSS 中我们可以通过 import 来导入一个样式文件,Sass 扩展了 CSS 的 import 规则,使得可以导入 CSS 后缀的样式文件和 Scss 后缀的样式文件,并且提供了对 mixin 、函数和变量的访问。 与 CSS 的 import…

AI技术的实际应用和影响

随着人工智能技术的快速发展,越来越多的AI工具开始出现在我们的生活中。这些工具在各个领域都发挥着重要的作用,为人们带来了便利和效率。在这篇文章中,我们将探讨人们在使用AI工具时最喜欢的和认为最好用的工具,并展示AI技术的实…

【QEMU系统分析之实例篇(三十五)】

系列文章目录 第三十五章 QEMU系统仿真的机器创建分析实例 qdev_connect_gpio_out_named(lpc_dev, ICH9_GPIO_GSI) 文章目录 系列文章目录第三十五章 QEMU系统仿真的机器创建分析实例qdev_connect_gpio_out_named(lpc_dev, ICH9_GPIO_GSI) 前言一、QEMU是什么?二、…

Python内置函数oct()详解

Python中的oct()函数是一个内置函数,用于将一个整数转换成它的八进制字符串表示。 函数定义 oct()函数的基本语法如下: oct(x)x:一个整数。 函数返回x的八进制表示,以字符串形式。 基本用法 将整数转换为八进制 number 64…

神经网络激活函数

一、为什么需要激活函数 通俗解释 想象一下你在玩乐高积木。你有各种不同颜色和形状的积木,你的任务是建造一个模型——也许是一辆车、一座房子,或者是一只动物。 如果你只允许每一块积木直接堆叠在另一块上面(想象一下只能垂直或水平地把…

深度学习模型的训练细节

摘要: 深度学习模型训练是复杂且细致操作的过程,涉及多个步骤和技巧。在训练深度学习模型时,中间变量的检查是至关重要的,它可以帮助我们理解模型的学习动态,获得真实的训练过程反馈,及时发现并解决问题。通…

初识C语言——第二十天

do while ()循环 do 循环语句; while(表达式); 句式结构: 执行过程: do while循环的特点: 代码练习: 二分法算法: int main() {int arr[] { 0,1,2,3,4,5,6,7,8,9};int k 7;//查找数字7,在arr这个数组…

80%的产品经理被辞退不是因为能力,而是因为…

新手刚入门做产品经理,对产品经理的工作其实也是没有把握,这是对这份工作不够了解,不知道整个工作的流程,所以会感觉“没把握”,结果就是导致焦虑。 如果你硬着头皮做一遍,知道大概是怎么回事,…

Advanced RAG 07:在RAG系统中进行表格数据处理的新思路

编者按: 目前,检索增强生成(RAG)系统成为了将海量知识赋能于大模型的关键技术之一。然而,如何高效地处理半结构化和非结构化数据,尤其是文档中的表格数据,仍然是 RAG 系统面临的一大难题。 本文作者针对这一…

中国仓储物流装备产业链上最全产品资料大全(目前238家公司产品资料……)...

导语 大家好,我是社长,老K。专注分享智能制造和智能仓储物流等内容。 新书《智能物流系统构成与技术实践》人俱乐部 知识星球【智能仓储物流技术研习社】内已经收录了如下中国230多家仓储物流装备和技术相关产业链的公司的产品手册,请星球会员…

Oracle GoldenGate 配置双向同步

Oracle GoldenGate 配置双向同步 一、环境准备 DB版本:19.3 GoldenGate版本:21.3 系统环境配置: mkdir -p /u01/app/ogg_home chmod -R 777 /u01/app/ogg_home chown -R oracle:oinstall /u01/app/ogg_home vi .bash_profile # oracle export CV_ASSUME_DISTID=OEL7 expo…

python-pytorch seq2seq+attention笔记1.0.2

python-pytorch seq2seq+attention笔记1.0.0 1. LSTM模型的数据size2. 关于LSTM的输入数据包含hn和cn时,hn和cn的size3. LSTM参数中默认batch_first4. Attention机制的三种算法5. 模型的编码器6. 模型的解码器7. 最终模型8. 数据的准备9. 遇到的问题10. 完整代码11. 参考链接记…

好文推荐:基于热红外的双源能量平衡(TSEB)模型--从植物到全球尺度的蒸散诊断简史

文献 近日,美国农业部农业研究服务局(USDA-ARS)的科学家们发表了一篇重要的研究论文——“Agricultural and Forest Meteorology” (https://www.sciencedirect.com/journal/agricultural-and-forest-meteorology)&…

智慧公厕系统:改变“上厕所”体验的科技革新

公共厕所是城市建设中不可或缺的基础设施,然而,由于较为落后的管理模式,会常常存在着管理不到位、脏乱差的问题。为了改善公厕的使用体验,智慧公厕系统应运而生,并逐渐成为智慧城市建设的重要组成部分。本文将以智慧公…

AI工具如何简化日常生活?从论文到PPT,AI助手大集合

AI助手大集合,猛戳进来! 在工作和生活中,我经常使用各种各样的人工智能工具,如AI写作软件、AI语音助手、AI绘图工具等。我发现,这些工具能够极大地提高工作效率并简化日常生活。作为一名AI工具的忠实爱好者&#xff0…