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和jquery对dom节点的操作(创建/追加)
Apr 21 Javascript
jQuery实现购物车表单自动结算效果实例
Aug 10 Javascript
简单谈谈javascript中的变量、作用域和内存问题
Aug 30 Javascript
浅谈javascript 函数表达式和函数声明的区别
Jan 05 Javascript
详解JavaScript时间处理之几个月前或几个月后的指定日期
Dec 21 Javascript
Bootstrap的modal拖动效果
Dec 25 Javascript
js中document.referrer实现移动端返回上一页
Feb 22 Javascript
angular实现IM聊天图片发送实例
May 08 Javascript
微信小程序滚动Tab实现左右可滑动切换
Aug 17 Javascript
React-Native中禁用Navigator手势返回的示例代码
Sep 09 Javascript
如何从零开始利用js手写一个Promise库详解
Apr 19 Javascript
微信小程序购物车、父子组件传值及calc的注意事项总结
Nov 14 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
smtp邮件发送一例
2006/10/09 PHP
9个实用的PHP代码片段分享
2015/01/22 PHP
php实现递归抓取网页类实例
2015/04/03 PHP
浅析PHP中call user func()函数及如何使用call user func调用自定义函数
2015/11/05 PHP
Zend Framework动作助手FlashMessenger用法详解
2016/03/05 PHP
php简单检测404页面的方法示例
2019/08/23 PHP
tp5.1 框架数据库常见操作详解【添加、删除、更新、查询】
2020/05/26 PHP
使用JavaScript库还是自己写代码?
2010/01/28 Javascript
另一个javascript小测验(代码集合)
2011/07/27 Javascript
JS字符串截取函数实例
2013/12/27 Javascript
jQuery及JS实现循环中暂停的方法
2015/02/02 Javascript
js文本框走动跑马灯效果代码分享
2015/08/25 Javascript
JS三级可折叠菜单实现方法
2016/02/29 Javascript
vue2.0多条件搜索组件使用详解
2020/03/26 Javascript
全面解析vue中的数据双向绑定
2017/05/10 Javascript
jQuery的Ajax接收java返回数据方法
2018/08/11 jQuery
Vuex的基本概念、项目搭建以及入坑点
2018/11/04 Javascript
vue-cli3 引入 font-awesome的操作
2020/08/11 Javascript
[02:29]DOTA2英雄基础教程 陈
2013/12/17 DOTA
[37:35]DOTA2上海特级锦标赛A组资格赛#1 Secret VS MVP.Phx第二局
2016/02/25 DOTA
python实现绘制树枝简单示例
2014/07/24 Python
Python抓取手机号归属地信息示例代码
2016/11/28 Python
python使用opencv按一定间隔截取视频帧
2018/03/06 Python
Python中print和return的作用及区别解析
2019/05/05 Python
python内存管理机制原理详解
2019/08/12 Python
给我一面国旗 python帮你实现
2019/09/30 Python
python使用协程实现并发操作的方法详解
2019/12/27 Python
解决pyecharts运行后产生的html文件用浏览器打开空白
2020/03/11 Python
Python获取对象属性的几种方式小结
2020/03/12 Python
python中四舍五入的正确打开方式
2021/01/18 Python
英国网上花店:Bunches
2016/11/29 全球购物
英国领先的维生素和补充剂品牌:Higher Nature
2019/08/26 全球购物
跟单文员的岗位职责
2013/11/14 职场文书
小学生三分钟演讲稿
2014/08/18 职场文书
三好学生评语大全
2014/12/29 职场文书
中学政教处工作总结
2015/08/13 职场文书