🔥Vue 初始化实例、静态成员过程源码调试(详细步骤)

76 阅读3分钟

大家好,我是金同学。话不多说,直接进入主题。来跟我通过调试源码一步一步看 Vue 初始化实例成员和静态成员的过程,从中学习 Vue 的相关知识点。

准备工作

首先把仓库代码拉到你本地,仓库源码地址在这里

拉下仓库代码后,执行以下两步:

  • 1、用 VsCode 打开仓库代码,先安装依赖,然后运行 npm run dev,这步为的是能在调试 Vue 代码时看到源文件。
  • 2、然后进到下图目录中,右击用 live-server 打开。

image.png

粮草先行 🛫 🛫 🛫

先主要复习下初始化过程涉及到的文件、函数等。

src/core/index.js

这个文件里面主要就是执行了 initGlobalAPI(Vue) 这个方法。initGlobalAPI(Vue)方法里面可做了不少事情,主要就是初始化静态成员...

  • 1、初始化了 Vue.config 对象
  • 2、初始化静态方法 set/delete/nextTick
  • 3、初始化 Vue.options 对象,并给其初始化了 componentsdirectivesfilters
  • 4、初始化 keep-alive 内置组件
  • 5、注册了 Vue.use() 用来实现插件机制
  • 6、注册了 Vue.mixin() 来实现混入机制
  • 7、注册了 Vue.extend() 来实现基于传入的 options 返回一个组件的构造函数
  • 8、注册了 Vue.directive()Vue.component()Vue.filter()来存放全局指令、组件、过滤器

我们在下图所示位置打上断点

image.png

src/core/instance/index.js

这个文件定义了 Vue 的构造函数,然后调用各种 mixinVue 的原型上混入各种实例成员,我们也简要概括下:

  • 1、initMixin(Vue)Vue 的原型上增加 _init()

  • 2、stateMixin(Vue)Vue 的原型上增加我们常用的一些属性和方法 $data/$props/$set/$delete/$watch

  • 3、eventsMixin(Vue)Vue 的原型上增加事件相关方法 $on/$once/$off/$emit

  • 4、lifecycleMixin(Vue)Vue 的原型上增加生命周期相关的方法_update/$forceUpdate/$destroy

  • 5、renderMixin(Vue)Vue 的原型上挂载了 $nextTick/_render

同样的,我们在下图所示位置打上断点

image.png

src/platforms/web/runtime/index.js

前两个文件都是处理和平台无关的核心代码,这个文件中处理了一些和平台相关的逻辑。(平台指浏览器平台(web 目录)和 weex 平台(weex 目录))

  • 1、这个文件中处理了 Vue.config 默认配置中的一些东西

  • 2、然后注册了和平台相关的全局指令(v-modelv-show)和全局组件(transitiontransition-group

  • 3、往原型上挂载了 __patch__$mount 方法

    • __patch__:把虚拟 DOM 转换成真实 DOM
    • $mount 就是挂载方法了

同样的,我们在下图所示位置打上断点

image.png

src/platforms/web/entry-runtime-with-compiler.js

这个文件是 Vue 打包时的入口文件,它打包的是完整版的 Vue ,即运行时和编译器都有。它里面主要做了下面这些事:

  • 1、重写了 Vue 原型上的 $mount 方法,增加了把模板编译成 render 函数的功能
  • 2、给 Vue 的构造函数增加了一个 Vue.complier() 方法,给开发者手动调用把模板编译成 render 函数

同样的,我们在下图所示位置打上断点

image.png

嘉陵关决战

做完上面这一堆起手式,高低得干一架了吧。按 command + r 刷新页面进入断点

刷新完页面后,应该会和我一样进入到下图所示吧(进入的是src/core/instance/index.js文件中的断点位置)

image.png

动手

先在右边那个 watch 面板添加 Vue 构造函数的监听,算了,我还是给个图吧。

image.png

从上图可以看到现在的 Vue 构造函数上面只有一些默认的成员,我们接下来就会看到往它上面挂载成员的详细过程。我们按 F10 或者下图中的那个图标跳过 initMixin(Vue) 的执行过程,在右边的 watch 面板就能实时观测到 Vue 构造函数上面比刚开始多了一个 _init() 方法。

image.png

这里就不执行一个函数贴一张图了,大家可以对着自己看看,没看清楚可以重新刷新页面来几次。然后就要进入下一个文件调试了朋友们😁,按 F8 或者下图中的那个图标跳到下一个断点。从下图中就能看到经过上一个文件(src/core/instance/index.js)中的操作后, Vue 构造函数原型上面多出来一大堆东西,当然有我们熟悉的“朋友”,也有陌生的“朋友”。

image.png

迄今所有人生都大写着失败,但不妨碍我们继续向前——狂铁

点击下图中的小箭头或者按 F11 进入到 initGlobalAPI() 方法中,然后就可以自己按 F10 一步一步跳过里面的函数同时观察右边 Watch 面板中 Vue 构造函数的变化情况了。每个文件中主要做的工作也都在上一小节粮草先行中写了,有需要可以回看下。

image.png

重复的操作我们就不走了,大家都是绝顶\color{#8470FF}{绝顶}聪明的程序员,接下来的就交给你们自己吧。F8 跳到下一个断点,F10 跳过函数的执行,F11 进入函数。

重复 debug 几次,应该就能对 Vue 初始化实例成员和静态成员的过程观察的非常清楚了。小子才疏学浅,有任何问题欢迎评论区留言哦。

下一次相遇

要是有下一篇,应该就是关于 Vue 首次渲染的详细 debug 过程了。

努力生活是头等大事,祝朋友们岁月静好。

image.png