core 源码阅读指南详解

最近又抽时间把 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,粗略的看了一下,发现耦合性比较低,因此可以日后再看

组件相关

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/fcf60f7a771739cb59a64e4ac1a1992e.html