关于源码的阅读

Vue源码

一直在阅读 Vue 框架及周边插件、库源码,却没有输出文章,总感觉缺少点什么,因为不知道自己是不是真的理解了,或者是理解正确了。接下来会将阅读 Vue 生态相关源码的过程和思考写出来,今天先说说为什么要阅读源码,以及我是怎么阅读源码的。

为什么要阅读源码

首先阅读框架的源码,能加深对框架原理的理解,这将有助于你在日常工作中快速定位和解决问题。

其次是阅读框架源码能学习到一些优秀的设计模式和编程技巧,这将有助于你写出更优雅、运行高效的代码。

再者就是阅读框架源码将有助于提升你的职场竞争力,有助于你跳槽、升职加薪。

我是怎么阅读源码的

阅读框架源码是一件非常“乏味”的事情,如果没有足够的耐心是坚持下去的。原因有几点,

  • 代码量大,让开发者望而生畏
  • 代码抽象程度比较高,晦涩难懂
  • 开发者个人的基础知识不充分,有些代码写法理解起来比较困难

所以要想坚持阅读源码,无非就是要克服以上几点困难,代码量太大,这个需要先从心理上说服自己,看源码没有人能一蹴而就的,都是一点一点慢慢看过来的,可以按功能或者模块逐个阅读,这样就不会感觉源码的体量太大。代码的抽象程度高,这是必然的,因为框架作者需要考虑源码的复用性、可维护性,自然会牺牲一定的可阅读性,这点困难其实也没有什么问题,只要自己多阅读、思考几遍,结合在源码中打断点进行调试,肯定是能理解的。至于最后一点的基础知识不足,这个就跟个人平时的积累有关系了,也急不来,平时有时间的时候多巩固一下自己的基础知识就好。

我阅读源码的方式比较倾向于先整体读一下概览,使用的工具是一个可以通过浏览器打开的 web 版VSCode,地址是 https://github1s.com,阅读源码相当方便,假如你想通过这个网站阅读 Vue 源码,只需要先打开 Vue 的 github 仓库地址https://github.com/vuejs/vue,然后在 github 的后面加上 1s 即可,也就是 https://github1s.com/vuejs/vue ,打开后的界面如下:

我是怎么阅读 Vue 源码的呢?第一步是先认识这个框架源码的目录结构,然后从项目的 package.json 文件开始,了解它的依赖和构建命令,然后找到源码的入口,大概过一遍源码,这个过程不过多的关注源码的细节,只要脑海中有个大概的印象就行。下一步就是借助官方的 demo,打断点调试。首先找到 package.json 文件,修改一下 dev 那一项的命令,以生成 sourcemap,借助 sourcemap ,当我们打断点的时候就能快速找到对应源码的位置:

然后根目录执行 npm run dev 命令,会在 dist 目录生成一个新的 vue.js 文件和 vue.js.map 文件。我是使用官方提供的 examples 目录下的 markdown 来打断点调试,所以我把 dist 文件夹复制到 markdown 文件夹下面,

然后修改一下 index.html 对 vue 的引用,并在实例化 Vue 之前打个 debugger:

这时候如果我们直接在浏览器中打开 index.html,虽然 demo 能正常跑起来,但是 sourcemap 功能是没起作用的,也就是开发者工具这时候不会去加载 sourcemap 对应的源文件,我们需要本地起一个 http 服务,可以借助 Nginx 或者 Node.js,我这里借助一个 node 插件:http-server,具体安装方式是在命令行工具运行 npm install -g http-server 即可,安装成功后,在 markdown 目录下打开一个命令行工具,然后运行 http-server 就能把本地服务跑起来了:

浏览器输入 http://127.0.0.1:8080 ,就能访问 markdown 应用了,如下图:

将鼠标悬停在 Vue 上,可以看到 new Vue 的时候执行的是源码中/src/core/instance/index.js中的 Vue 构造函数代码,在构造函数内也打一下断点,并继续运行,如下图:

可以看到 Vue 构造函数内部只执行了一行代码,调用了一个 _init 方法,这个方法从哪儿来的呢,可以将鼠标悬停到方法名上,可以看到这个方法是被注册到 Vue 的原型上的,具体的位置是在源码的 /src/core/instance/init.js 文件,如下图:

这个_init 方法是什么时候被注册到 Vue 原型上的呢?全局搜索一下 initMixin ,可以发现是在 /src/core/instance/index.js :

就按上面这些步骤进行调试,就能将 Vue 底层运行机制彻底搞懂,包括数据的响应式处理、模板编译、事件/指令处理、生命周期、diff 更新过程等。

发表评论

邮箱地址不会被公开。 必填项已用*标注