前一篇文章我们探究了这个app是怎么被创建出来的,这一章我们探究一下当我们用这个app对象的mount方法时,vue内部发生了什么,它是怎么样挂载到dom上的。
首先看一下mount方法
它首先拿到我们传入的组件生成vnode,然后把生成的vnode和根元素传入render函数中
这里调用patch(null,vnode,container),这边调用完会执行flushPostFlushCds()这个函数的目的是执行生命周期的回调。和把这一次的vnode放到dom节点的_vnode属性上。接下里看一下patch函数
patch函数根据n2中的shapeFlag属性分了很多种情况。第一次进行会调用processComponent()函数
在processComponent()中,由于n1为null,所以它去调用了mountComponent()
在mountComponent()中上来就根据传入的vnode创建了一个instance,之后在setupComponent()中传入这个instance,这函数最主要的目的是执行setup(),根据template创建render函数
可以看到它拿出setup把它放出callwithErrorHandling中执行了一遍,在执行过程中比如有调用ref,watch这些api,它就处理这些api,完成之后返回setup()中的返回值setupResult
之后编译template,把它放在instance.type中。这部分先不详细描述了,之后在专门的章节会写。我们先来梳理构建流程。之后回到mountComponent()中往下走,调用setupRenderEffect()
看一下这个函数内部做了什么。
它先是定义了一个componentUpdateFn函数。之后调用ReactiveEffect生成一个副作用对象。目的是在instance.scope.effects中添加这次的effect。之后执行update(),相当于执行了componentUpdateFn()
componentUpdateFn()中比较关键的是它这次拿了subTree又patch了一遍,并且把在setup中定义的onMount函数的回调放入调用栈中。到这mount结束,组件挂载完成。之后执行之前的flushPostFlushCds()看看有没有需要回调的函数。这里就是指的是onmount的回调。