Vue3组件初始化流程(三): 验证对createApp以及mount的分析,并总结初始化流程 [Vue3源码系列_xiaolu]

19 篇文章 9 订阅

搭建验证环境

这一章我们来验证前两章的分析

首先,在packages/vue/expample下面新建一个文件index.html

index.html 路径: core\packages\vue\examples\init.html

<div id="app">
  <h1>{{title}}</h1>
  <p>someText</p>
</div>

<script src="../dist/vue.global.js"></script>

<script> 
  Vue.createApp({
    setup() {
      return {
        title: 'vue3初始化流程'
      }
    }
  }).mount('#app')
</script>

这是一段非常简单的代码,相信大家肯定都知道这段代码在页面中会如何显示

那么现在就从这段简单的代码开始我们的验证

验证createApp

首先验证createApp

第一章中给出的结论是: 用户调用的createApp其实是调用createAppAPI方法返回的createApp方法

回想一下

  1. 当时是从todomvc调用的createApp出发,进入到ensureRenderer内部
  2. 在enusreRenderer内部其实是调用了createRenderer返回的渲染器对象的createApp方法
  3. 而createRenderer又返回baseCreateRenderer调用的返回值,这个返回值就是渲染器
  4. 渲染器内部的createApp方法是createAppAPI方法调用的返回值
  5. 而createAppAPI方法返回一个createApp方法

所以最后我们执行的就是这个createApp方法

因此我们第一章得出的调用栈是如此:

createApp -> ensureRenderer -> createRenderer -> baseCreateRenderer -> createAppAPI

现在我们开始打断点,将断点打在createAppAPI这里,就可以看到调用栈了 如图

路径为: core\packages\runtime-core\src\apiCreateApp.ts

1_createAppAPI断点.png

刷新,看调用栈,如图

2_createAppAPI调用栈.png

可以看到,实际的调用栈与我们从代码里看到的是一样的,所以关于createApp的调用分析是正确的

验证mount

接着验证mount

回想一下

  1. mount方法内部会执行render方法
  2. render方法内部会执行patch方法
  3. patch方法会执行processComponent方法
  4. processComponent方法会执行mountComponent方法

因此我们第一章得出的调用栈是如此:

mount -> render -> patch -> processComponent -> mountCompoent

接下来开始验证,将断点打在mountCompoent内部,如图3

路径: core\packages\runtime-core\src\renderer.ts

3_mountComponent断点.png

刷新,看调用栈,如图

4_mountCompoent调用栈.png

可以看到,实际的调用栈与我们从代码里看到的是一样的,所以关于mount的调用分析是正确的

验证mountComponent的三个方法

接下来就是看mountComponent内部的三个方法:

  1. createComponentInstance 创建组件实例
  2. setupComponent 初始化组件实例
  3. setupRenderEffect 创建更新函数,机制,首次视图更新

验证createComponentInstance

这个函数就是创建instance实例,还未初始化,所有属性都是null之类的

要验证的话,可以将断点打在setupComponent这里,看看在进入setupComponent函数前的instance是什么样就知道了,如图

5_创建组件实例断点.png

可以看到此时instance上的属性全是null,因此createComponentInstance确实是用来创建组件实例

验证setupComponent

验证setupCompoent

回想一下

第二章我们得出的是:

  1. setupComponent内部会执行setupStatefulComponent
  2. setupStatefulComponent执行handleSetupResult
  3. handleSetupResult会执行finishComponentSetup

因此我们第二章得出的调用栈是如此:

setupComponent -> setupStatefulComponent -> handleSetupResult -> finishComponentSetup

我们将断点打在finishComponentSetup内部,如图

路径: core\packages\runtime-core\src\component.ts

6_finishCompoentSetup断点.png

刷新,看调用栈,如图

7_finishComponentSetup调用栈.png

可以看到执行流程是分析正确的

但是还要验证功能是否分析正确,我们之前说了经过setupComponent后,instance会有render,setupState(setup存在的情况),还有初始化了props,attrs和slots,所以应该在instance上看到他们

还是刚刚的断点,我们只要进行下一步,然后去查看instance,如图

8_setupComponent之后的属性.png

可以看到,上面有slots render setupState等属性

注意setupState的值,如图

9_setupState的值.png

可以看到,title,不就是我们前面代码里面的的title吗?

因此功能分析基本正确

setupRenderEffect

验证setupRenderEffect

我们之前得出的结论是创建更新函数,建立更新机制,视图首次更新

因为更新机制涉及到响应式模块,先不管他

我们要验证的是:

  1. update执行的时候,是执行我们创建的更新函数componentUpdateFn去render和patch
  2. 并且update执行完毕后,界面渲染完毕

因此断点打在update执行的地方,如图

路径: core\packages\runtime-core\src\renderer.ts

10_update断点.png

刷新,此时我们可以看到界面是空白的,代表数据还没渲染如图

11_update之前.png

点击下一步,别点错了哦,点到下一个断点的话,页面直接刷新会让你误判的 如图

12_点这个.png

可以看到,界面渲染完毕了!如图

13_update之后.png

此时,验证了update确实是做了首次视图更新

接下来验证update的执行流程

我们之前说update是effect.run其实就是执行componentUpdateFn

猜测的调用栈:

update -> effect.run -> componentUpdateFn

因此断点打在render和patch这里如图

路径: core\packages\runtime-core\src\renderer.ts

14_render_patch.png

刷新,看调用栈,如图

15_调用栈.png

差别不大,run -> componentUpdateFn

其实再细分的话,patch执行完之后,视图就会更新,来看看,跳到patch断点,然后下一步,看看视图是不是更新了。

验证patch的递归调用

我们将断点打在patch中的switch(type)这里,这样就可以看看执行了多少次patch。如图

路径: core\packages\runtime-core\src\renderer.ts

16_patch的断点.png

一直跳到下一个断点,就可以看到,patch执行了四次,如图

17_patch递归.png

结合index.html中的

<div id="app">
  <h1>{{title}}</h1>
  <p>someText</p>
</div>

可以看到:

  1. 第一次肯定是component
  2. 第二次是fragment(vue3中,当出现两个元素时,就会用Fragment将其包起来,这里就是包裹了h1和p,可以去看看processFragment,其实就是patchChildren)
  3. 第三次是h
  4. 第四次是p

这样四次,所有节点都已经patch完毕了

因此patch递归调用直到整个节点树渲染完毕是分析正确的

组件初始化流程

验证完前两章的分析之后,我们也可以总结一下组件初始化流程了

createApp().mount()这一句的执行流程如下图

18_.png

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值