「这是我参与2022首次更文挑战的第19天,活动详情查看:2022首次更文挑战」
vue3创建组件的过程探究
vue3中,我们执行createApp到底发生了什么呢,接下来,我们来一步一步的捋一下。
创建vue实例时,我们经常使用createApp(),然后通过ceateApp函数返回的app对象,来使用mount()来挂载我们的组件。接下来,我们来看一下createApp()和mount()在源码中的执行流程。
createApp
我们使用createApp(),使用的是vue源码中runtime-dom/src/index.ts文件导出的createApp函数。
-
调用runtime-dom/src/index.ts中导出的createApp函数。
-
createApp()中调用ensureRenderer( )
-
ensureRenderer( )中调用createRenderer( )
-
createRenderer( )中调用baseCreateRenderer(),baseCreateRenderer返回
{render, hydrate, createApp: createAppAPI(render, hydrate)}
-
最后实际上我们调用的是createAppAPI( )中返回的createApp函数。
-
最后执行完createApp以后,返回app对象,app对象中包含mount,use,mixin,component,directive,provide等全局api方法。
执行mount
-
执行createApp中的mount()函数
-
mount中调用baseCreateRenderer返回值中的render()渲染函数。
-
如果vnode不为null,则执行patch(),挂载vnode.
-
patch()中会进行类型判断,在这里我们是一个组件,因此执行processComponent
- 是组件则执行processComponent。
- 是元素则执行processElement
- 是fragement则执行processFragment
-
执行processComponent中的mountComponent()
-
mountComponent() 中先执行createComponentInstance(),创建组件实例,然后执行setupComponent(),初始化组件实例。
-
调用设置和渲染有副作用的函数,setupRenderEffect()
-
setupRenderEffect(),如果没有根元素,则获取到subTree。(subTree是用Fragement包裹的所有元素)
-
执行patch函数
-
有根元素,则执行processElement().
-
如果有n1(旧vnode)为null,则执行mountElement,否则执行patchElement.
-
mountElement中根据vnode,通过hostCreateElement()创建真实的element.
-
如果有子元素,则通过mountChildren()挂载子元素。
-
最后通过hostInsert(),将el挂载到container中。
setup初始化实例
- 处理props和attrs
- 处理slots
- 执行setup()
- 编译tempalte,将template模板转为render函数。
- 对vue2中options API 进行处理。
比较浅的解析vue3中创建组件的流程,后续添加详细的解析。