vue-next/runtime-core 源码阅读指南详解


Posted in Javascript onOctober 25, 2019

写在前面

最近又抽时间把 vue-next/runtime-core 的源码陆陆续续地看完了,期间整理了很多笔记,但都是碎片化的。本来是想整理一下,写成一篇文章分享出来的,但是感觉最终的成果物只能是一篇篇幅巨长的解析文,就算我一行一行的把源码加上注释,其阅读体验也会很差,因为每个人读代码的习惯不同,思路不同。正所谓抛砖引玉,所以,我觉的写一篇向导文作为这块砖应该是足够了,希望可以帮助到想看源码但觉得无从看起、无从下手的读者。

另一方面,也算是给自己挖一个坑,因为这篇文章中涉及到的很多内容,三言两语肯定是说不清的,这就意味着之后必须要写其他文章来填补这些空白。我会尽可能的将高内聚的模块整理到一起,然后再分享出来,尽量避免陷入罗列代码的境地,从而提高文章质量吧。

阅读笔记我托管在语雀上,不嫌乱的也可以看这里。

准备工作

工欲善其事,必先利其器,要看源码,拿写字板来看肯定是不行的(当然也不排除牛人)。你所需要的就是一个支持代码跳转的编辑器即可,我用的是 VSCode,当然了,如果你用 VIM、Sublime 也是可以的。

另外还需一些储备知识:

  • 由于是阅读 vue-next 的代码,并且是 pre-alpha 的版本,这就要求你对之前 vue 有一定的了解,如果是第一次接触,我觉的阅读源码的意义也不是很大
  • 需要熟练掌握 debug 的基础技巧和流程,通过 debug 的方式来看代码有两个好处
    • debug 过程有清晰地调用栈记录
    • 各种作用域下的变量一目了然
  • 需要对 typescript 有一定掌握程度,最起码给知道 interface、enum 等概念

如何阅读

一般有三种途径:

  • 直接看
  • 通过单元测试的可执行代码
  • 自己编写的可执行代码

这里推荐第二种方式,因为单元测试是官方团队维护的,质量肯定有保证,二来单元测试一般都很简单,同时带有注释,这有利于我们理解代码。

由于 vue-next 使用 jest 进行单元测试,在 vscode 中安装 Jest 插件即可,它支持行内 debug lens 快捷入口,方便直接对某条单元测试进行 debug。

不过要注意配置一个自定义选项:

"jest.debugCodeLens.showWhenTestStateIn": [
  "fail",
  "unknown",
  "pass", // 注意这里
]

这里的 "pass" 代表即使单元测试通过,也会在上方显示 debug lens,默认情况下,单元测试用例通过的话,这个 debug lens 标识不会显示。

模块职能归纳

runtime-core 目录下有多个文件,我暂且把每个文件都当做一个子模块来看待。vue 的代码质量还是挺好的,模块与模块之间的耦合性都不是特别高,正因为如此,基本上每个模块都有自己单独对应的单元测试文件。

我在看的时候,基本上就是挨个看这些模块的单元测试,然后调试过程中,会主动的进行一些代码跳转,去看一下具体的实现细节。下面把当前最新代码下该文件目录下的所有模块的职能进行一些总结和归纳。

有一些较独立的模块我还没有看完,但是不影响整体的源码阅读进程,日后对这些独立模块进行单独研究时,才回来补充这些 todo 就好了。

公共 api 相关

实现公共 api 的模块均是以 apixxx 这样的格式来命名的,如下:

  • apiApp.ts: 有 3 个比较重要的接口需要看一下,App、AppConfig 和 AppContext,如果对于 vue2 比较熟悉的话,会很容易理解。createApp 是一个工厂方法,返回一个符合 App 接口约束的对象,其内部方法会与一个符合 AppContext 接口约束的对象进行交互。
  • apiCreateComponent.ts: 这个文件内部包含多个对于 createComponent 函数签名的重载声明,其存在目的应该是为了帮助 ts 提供更好的类型推断以提升开发体验。
  • apiInject.ts: 组件依赖注入 feature 的实现逻辑,实现方式很简单,直接与 component 文件中暴露的 currentInstance 变量进行交互,实现继承、赋值、取值等逻辑
  • apiLifecycle.ts: 新的组件声明周期 hooks,主要看 injectHook 方法就可以了,这里的 target 默认情况下指向 currentInstance,之后会在将某个回调逻辑缓存在 currentInstance 实例的声明周期回调函数数组中
  • apiOptions.ts:其中包含对于 component 如何解析 options 的实现逻辑,代码比较长同时也比较复杂,耦合性与其他几个文件较高。但其实没有必要直接看完它内部的全部代码,因为 options 中每一段的解析逻辑互相之间都是独立的,因此可以专门针对某个 option 单独去看它内部的解析逻辑,我目前只看了 data 以及 lifecycle。
  • apiReactivity.ts:就是对 reactivity 包中的 api 的重新导出,没有什么额外的东西
  • apiWatch.ts: 暂时还没仔细看,不过根据名字可知是和 watch 相关的 api,粗略的看了一下,发现耦合性比较低,因此可以日后再看

组件相关

  • component.ts: 主要包含如何创建一个内部组件实例的逻辑,代码比较长,但是点进去看的话,会发现它其实是在调用其他模块的暴露的 api,本身的逻辑还是比较简单的。需要注意的是,这个文件会暴露一对 setCurrentInstance 和 getCurrentInstance 方法用来维护 currentInstance 变量的指向,同时它会在别的模块中被使用到
  • componentProxy.ts: 声明了 render proxy 的实现逻辑,这个 proxy 主要负责外部如何与内部组件实例进行交互,可以将它看做是一个外部组件实例
  • componentProps.ts: 主要看 resolveProps,实现了如何解析各种形式的 props
  • componentSlots.ts:主要看 resolveChildren,实现了如何解析各种形式的 children 节点
  • componentRendererUtils.ts: 一些渲染组件的 util 方法,按名字了解各个方法的含义即可
  • createRenderer.ts:这个和其他文件耦合度较低,可以理解为 VNode 的渲染器,只要实现了其接口,可以在任何上下文环境中进行渲染,比如小程序、native、canvas 或者内存环境,关于如何编写一个 renderer,直接看 runtime-test 或者 runtime-dom 的代码即可
  • directives.ts: 指令相关的内部 api,当前的代码版本,这部分可能很多 todo 因此可以日后再回来看看

其他

  • errorHandling.ts: 错误处理相关,暂时还没仔细看
  • scheduler.ts: 作业调度器相关,暂时还没仔细看
  • shapeFlags.ts: 组件本身和 children 类型的枚举声明及常量
  • suspense.ts: suspense 相关,暂时还没看,对于其他文件中的 suspense 的相关逻辑,我完全是按照 react 中相关概念来理解的,暂时没遇到任何障碍
  • warning.ts: 警告相关,大部分是一些 util 方法,按名字理解其含义就好了

推荐的阅读顺序

直接说我自己的阅读顺序,我认为还是比较符合认知习惯的:

  • 先看 vnode.ts 和 h.ts 等关于 vdom 的代码了解一下新的 VNode 的数据结构
  • 然后再看 apiApp.ts,看挂载过程是怎样把 VNode 和渲染上下文关联起来的,这个过程中自然会涉及到各种 apixxx.ts 中的内容,挨个看就好了
  • 由于之前看的都是公共 api,需要了解实现细节的话,要进一步看 component.ts,其中主要包含内部组件实例的数据结构以及创建流程,同样地,打断点一行一行读即可
  • 对于一些解析、工具方法,可以放到最后再看其实现细节,打断点的过程中没有必要一探到底,因为有些方法的名字已经可以很明确的说明其背后实现的逻辑是什么了

期间会遇到 suspense、lifecycle 之类的代码,这类代码也可以当做单独的内容进行阅读,在一开始看的时候,也可以不要太纠结于细节,当对整体流程有一个大概了解之后再回头来看会清晰很多,之后我会专门整理一篇文章介绍这块是如何实现的。

写在最后

虽然 vue-next 的代码现在还处在初期的阶段,但是整体的阅读体验还是不错的,结构清晰,可读性也比较高,一些关键模块也有注释进行说明,唯一不足的地方在于,很多地方还是借助 as 关键字来进行类型断言,我觉得这些地方可能有更好的方式实现类型推断吧。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
用JS实现一个页面多个css样式实现
May 29 Javascript
让浏览器非阻塞加载javascript的几种方法小结
Apr 25 Javascript
简单的代码实现jquery定时器
Jan 03 Javascript
JavaScript设计模式初探
Jan 07 Javascript
浅析Node.js实现HTTP文件下载
Aug 05 Javascript
IntersectionObserver实现图片懒加载的示例
Sep 29 Javascript
Validform验证时可以为空否则按照指定格式验证
Oct 20 Javascript
element-ui 中的table的列隐藏问题解决
Aug 24 Javascript
基于JavaScript实现一个简单的Vue
Sep 26 Javascript
深入解析koa之异步回调处理
Jun 17 Javascript
vue 实现滚动到底部翻页效果(pc端)
Jul 31 Javascript
在vue中实现嵌套页面(iframe)
Jul 30 Javascript
JS实现简单tab选项卡切换
Oct 25 #Javascript
vue项目从node8.x升级到12.x后的问题解决
Oct 25 #Javascript
JS实现骰子3D旋转效果
Oct 24 #Javascript
Vue可自定义tab组件用法实例
Oct 24 #Javascript
js实现转动骰子模型
Oct 24 #Javascript
js实现固定区域内的不重叠随机圆
Oct 24 #Javascript
js实现随机div颜色位置 类似满天星效果
Oct 24 #Javascript
You might like
PHP MSSQL 存储过程的方法
2008/12/24 PHP
PHP CURL CURLOPT参数说明(curl_setopt)
2013/09/30 PHP
thinkPHP数据库增删改查操作方法实例详解
2016/12/06 PHP
php抽象类和接口知识点整理总结
2019/08/02 PHP
一个加载js文件的小脚本
2007/06/28 Javascript
js实现图片旋转的三种方法
2014/04/10 Javascript
jQuery截取指定长度字符串代码
2014/08/21 Javascript
JS实现点击按钮自动增加一个单元格的方法
2015/03/09 Javascript
js实现简单的验证码
2015/12/25 Javascript
Javascript基础_嵌入图像的简单实现
2016/06/14 Javascript
Bootstrap整体框架之JavaScript插件架构
2016/12/15 Javascript
jQueryUI 拖放排序遇到滚动条时有可能无法执行排序的小bug及解决方案
2016/12/19 Javascript
详解js中==与===的区别
2017/01/08 Javascript
基于vue-resource jsonp跨域问题的解决方法
2018/02/03 Javascript
js中apply和Math.max()函数的问题及区别介绍
2018/03/27 Javascript
vue监听input标签的value值方法
2018/08/27 Javascript
详解一个基于react+webpack的多页面应用配置
2019/01/21 Javascript
jQuery实现条件搜索查询、实时取值及升降序排序的方法分析
2019/05/04 jQuery
实例讲解React 组件
2020/07/07 Javascript
[01:02:30]Mineski vs Secret 2019国际邀请赛淘汰赛 败者组 BO3 第三场 8.22
2019/09/05 DOTA
Python中的引用和拷贝浅析
2014/11/22 Python
Python 列表list使用介绍
2014/11/30 Python
Python命令行参数解析模块optparse使用实例
2015/04/13 Python
Python升级导致yum、pip报错的解决方法
2017/09/06 Python
Django REST框架创建一个简单的Api实例讲解
2019/11/05 Python
Python3 hashlib密码散列算法原理详解
2020/03/30 Python
详解Python yaml模块
2020/09/23 Python
Python自动化测试基础必备知识点总结
2021/02/07 Python
HTML5印章绘制电子签章图片(中文英文椭圆章、中文英文椭圆印章)
2019/06/03 HTML / CSS
HTML5有哪些新特征
2015/12/01 HTML / CSS
Timex手表官网:美国运动休闲手表品牌
2017/01/28 全球购物
主键(Primary Key)约束和唯一性(UNIQUE)约束的区别
2013/05/29 面试题
人资专员岗位职责
2014/04/04 职场文书
自我推荐信范文
2014/05/09 职场文书
2015年计算机教学工作总结
2015/07/22 职场文书
三八红旗手主要事迹材料
2015/11/04 职场文书