文章转载自:https://zhuanlan.zhihu.com/p/85978064

我们阅读源码的原因是什么?无非是1:学习;2:更好的使用这个库。如果只是想大致的了解下原理,倒不必花时间阅读源码,几句话,几张图就能搞清楚,网上搜搜应该就有很多。因此,阅读源码的过程一定是要对不明白的地方深入了解,肯定是很费时间的。

在这过程中,有些知识点,跟库本身可能没什么关系,但如果不懂,又难继续理解。对于这些知识点,我会尽量少的解释,但会贴上尽量完善的文档,方便不了解的同学先阅读学习。

前言

在上篇文章中说道,ref是最影响源码阅读的文件。但如果不先搞明白它,看其他的只会更晕。我先帮大家理清ref的逻辑跟概念。

由于现在(2019/10/9)vue@3还未正式发版,大家还不熟悉其相关的用法。上篇文章虽然介绍了不少,但其实还是有不少疑问。在阅读本篇文章之前,如果有时间,建议先阅读Vue官方对Composition API的介绍: 1. Vue Composition API 2. Ref Vs Reactive

读完关于Composition API的介绍,会对了解本库有更多认识,便于更好的理解源码。

ref跟reactive是整个源码中的核心,通过这两个方法创建了响应式数据。要想完全吃透reactivity,必须先吃透这两个。

Ref

ref最重要的作用,其实是提供了一套Ref类型,我们先来看,它到底是个怎么样的数据类型。(为了更好的做解释,我会调整源码中的接口、类型、函数等声明顺序,并会增加一些注释方便阅读)

要想了解UnwrapNestedRefs与UnwrapRef,必须先要了解ts中的infer。如果之前不了解,请先阅读相关文档。看完文档,再建议去google一些案例看看加深下印象。

现在我们假设你了解了infer概念,也了解了它的日常用法。再来看源码:

如果还是懵,建议后续再去看看infer的相关介绍。在这我们直接抛结果:

Ref是这样的一种数据结构:它有个key为Symbol的属性做类型标识,有个属性value用来存储数据。这个数据可以是任意的类型,唯独不能是被嵌套了Ref类型的类型。 具体来说就是不能是这样 Array 或者这样 { [key]: Ref }。但很奇怪的是,这样Ref 又是可以的。具体为什么也不知道,所以我勇敢地提了个PR...

(果然Ref 是不够完美的,2019.10.10晚,我这PR被合并了。大家遇到疑问时,也可以勇敢的提PR,说不定就被合了....)

另外,Map、Set、WeakMap、WeakSet也是不支持解套的。说明Ref数据的value也有可能是Map这样的数据类型。

说回Ref,从上篇文章中,我们已经了解到,Ref类型的数据,是一种响应式的数据。然后我们看其具体实现:

其实最难理解的就在于这个ref函数。我们看到,这里也定义了get/set,却没有任何Proxy相关的操作。在之前的信息中我们知道reactive能构建出响应式数据,但要求传参必须是对象。但ref的入参是对象时,同样也需要reactive做转化。那ref这个函数的目的到底是什么呢?为什么需要有它?

在文章开头,我贴了这份官方介绍Ref vs Reactive,这其中其实已经说的很明白。

However, the problem with going reactive-only is that the consumer of a composition function must keep the reference to the returned object at all times in order to retain reactivity. The object cannot be destructured or spread:

对于基本数据类型,函数传递或者对象解构时,会丢失原始数据的引用,换言之,我们没法让基本数据类型,或者解构后的变量(如果它的值也是基本数据类型的话),成为响应式的数据。

// 我们是永远没办法让`a`或`x`这样的基本数据成为响应式的数据的,Proxy也无法劫持基本数据。const a = 1;const { x: 1 } = { x: 1 }

但是有时候,我们确实就是想一个数字、一个字符串是响应式的,或者就是想利用解构的写法。那怎么办呢?只能通过创建一个对象,也即是源码中的Ref数据,然后将原始数据保存在Ref的属性value当中,再将它的引用返回给使用者。既然是我们自己创造出来的对象,也就没必要使用Proxy再做代理了,直接劫持这个value的get/set即可,这就是ref函数与Ref类型的由来。

不过单靠ref还没法解决对象解构的问题,它只是将基本数据保持在一个对象的value中,以实现数据响应式。对于对象的解构还需要另外一个函数:toRefs。

通过遍历对象,将每个属性值都转成Ref数据,这样解构出来的还是Ref数据,自然就保持了响应式数据的引用。但是源码中有一点要注意,toRefs函数中引用的是toProxyRef而不是ref,它并不会在get/set中注入track跟trigger,也就是说,向toRefs传入一个正常的对象,是不会返回一个响应式的数据的。必须要传递一个已经被reactive执行返回的对象才能有响应式的效果。感觉这点可以优化,暂时也不知道小右这样做的原因是什么。由于这里会牵扯到track跟trigger,而这两个在我写本文时还没研究,就没胆子提PR了。

到这,我们就把ref的源码给看完了。

eltree ref什么时候有_Vue3响应式系统源码解析-Ref篇相关推荐

  1. java 自适应响应式 网站 源码 SSM 生成 静态化 手机 平板 PC

    前台: 支持(5+3[时尚单页风格]) 八 套 模版, 可以在后台切换 点击: 获取地址 QQ 313596790 官网 http://www.fhadmin.org/ 系统介绍: 1.网站后台采用主 ...

  2. vue 实现 web端滚动刷新 排序 筛选 响应式布局 (源码)

    vue 实现 web端滚动刷新 排序 筛选 响应式布局 先展示效果图 源码: <template><div> <!-- 头部--><div class=&qu ...

  3. html期末大作业Bootstrap医疗器械公司响应式网站源码0014

    html期末大作业Bootstrap医疗器械公司响应式网站,兼容手机端 项目截图: 部分代码展示 <!DOCTYPE html><html ><head><t ...

  4. 【Vue 3.0 新特性(四)】Vue 3.0 响应式系统原理

    文章前言 笔记来源:拉勾教育 大前端高薪训练营 阅读建议:内容较多,建议通过左侧导航栏进行阅读 Vue 3.0 响应式系统原理 基础回顾 Vue.js 响应式回顾 Proxy 对象实现属性监听 多层属 ...

  5. 【Vue.js源码解析 一】-- 响应式原理

    前言 笔记来源:拉勾教育 大前端高薪训练营 阅读建议:建议通过左侧导航栏进行阅读 课程目标 Vue.js 的静态成员和实例成员初始化过程 首次渲染的过程 数据响应式原理 – 最核心的特性之一 准备工作 ...

  6. Vue3.0源码解读 - 响应式系统

    一.目标对象标识 ** 类似于渲染系统,vue3.0的响应式系统也有自己的一套flag,用于标记目标对象target(通常是我们传入的数据源)的一些特性 export const enum React ...

  7. 深入剖析Vue源码 - 响应式系统构建(上)

    从这一小节开始,正式进入Vue源码的核心,也是难点之一,响应式系统的构建.这一节将作为分析响应式构建过程源码的入门,主要分为两大块,第一块是针对响应式数据props,methods,data,comp ...

  8. 意外的服务器响应_响应式系统reactive system初探

    初识响应式系统 第一次听到reactive这个词还是在几年前,偶然了解到了Rxjava这个项目,仿佛为我打开了一扇新的大门,Rxjava是ReactiveX的java实现,ReactiveX家族除了R ...

  9. 响应式系统reactive system初探

    文章目录 初识响应式系统 什么是响应式系统 响应式系统的四大特点 及时响应性(Responsive) 恢复性(Resilient) 有弹性(Elastic) 消息驱动(Message Driven) ...

最新文章

  1. 又一所双一流大学明确:发表论文数量不再作为博士毕业的限制性条件
  2. python语言入门w-Python算法基础
  3. 实模式与保护模式详解一:寄存器
  4. 锻造「明星产品」的艺术与科学,在于取舍【附乔布斯张小龙的产品设计原则】...
  5. 修改linux下全局数据库名,linux/unix下修改oracle数据库实例名的方法
  6. 打破BERT天花板:11种花式炼丹术刷爆NLP分类SOTA!
  7. dbv mysql_MariaDB与MySQL对比 --- 对分布式事务的支持
  8. 百万奖金!天池发起广东工业制造创新大赛
  9. vs.net 2005中引用webservice的简单方法
  10. govendor用法
  11. 生物技术制药课程文献调研报告撰写说明
  12. 使用rundll32.exe绕过应用程序白名单(多种方法)
  13. POJ - 3494
  14. 前端页面常用代码参考
  15. DB2数据库的备份还原详解
  16. java替换特殊字符_Java处理特殊字符替换(正则表达式)
  17. PySpark之电商广告推荐(1)
  18. matlab实现三分之一倍频程,三分之一倍频程程序
  19. 【财富空间】一个人彻底的改变 一定始于内心的改变
  20. 假设有一个字类型的数值arry1,试编写程序统计arry1数值及其后若干数值,在字单元中存储时每个数据中含“1”数据位的个数,并将统计结果保存在res1数组中。数据段的代码定义如下: data seg

热门文章

  1. 腾讯招.NET要求以下几点,你准备好了吗?
  2. AWS 宣布创建“真正”开源的 Elasticsearch 分支
  3. ASP.NET Core Blazor 初探之 Blazor Server
  4. Sql Server之旅——第九站 看看DML操作对索引的影响
  5. .NET Core开发实战(第23课:静态文件中间件:前后端分离开发合并部署骚操作)--学习笔记(上)...
  6. 一篇文章看懂Git是什么以及如何简单的上手Git
  7. 关于WinForms的跨显示器DPI自适应
  8. 性能是.NET Core的一个关键特性
  9. Ocelot中使用Butterfly实践
  10. 想使用Docker容器?先看看这些注意事项