返回
Vue3 源码解析系列 - 挂载组件
前端
2023-10-01 13:50:15
前言
在patch过程中,如果是组件的话会执行mountComponent
方法进行挂载。这篇我们来看下这个方法做了些什么。
mountComponent
方法
mountComponent(initialVNode, container, anchor, parentComponent, parentSuspense, isSVG, optimized) {
const instance = vnode.component = createComponentInstance(vnode, parentComponent, parentSuspense, optimized);
if (isKeepAlive(vnode)) {
instance.ctx.renderer = keepAliveInstance!.ctx.renderer;
}
// inject renderer context
// merge renderer context if previous component is kept-alive.
const rendererContext = instance.ctx.renderer = instance.props && instance.props.rendererContext || parentComponent && parentComponent.ctx.renderer;
// resolve props and slots for setup context
{
const propsOptions = vnode.type.props;
setupStatefulComponent(instance, propsOptions, initialVNode, rendererContext);
}
// setup() is async. This component relies on async logic to be resolved
// before proceeding
if (instance.asyncDep) {
parentComponent && parentComponent.asyncDep!.catch(err => {
handleError(err, instance, 0 /* SETUP_FUNCTION */);
});
return true
}
finishComponentSetup(instance, parentComponent, initialVNode, rendererContext);
}
-
首先创建一个组件实例,并将其赋值给
vnode.component
属性。组件实例是组件运行时的一个实例化对象,它包含了组件的状态、方法和生命周期钩子等。 -
如果组件是一个KeepAlive组件,则将KeepAlive组件实例的
renderer
属性赋值给当前组件实例的ctx.renderer
属性。KeepAlive组件是Vue中的一种特殊组件,它可以缓存组件实例,并在组件切换时进行复用。 -
合并渲染器上下文。如果当前组件有父组件,则将父组件的
ctx.renderer
属性与当前组件的props.rendererContext
属性合并,并赋值给当前组件的ctx.renderer
属性。渲染器上下文包含了组件渲染相关的各种信息,如当前组件的渲染父节点、组件的渲染位置等。 -
解析组件的props和slots。解析组件的props和slots,并将解析结果赋值给当前组件实例的
ctx
属性。ctx
属性包含了组件的props、slots、组件实例本身等信息。 -
如果组件的
asyncDep
属性存在,则说明组件的setup
方法是一个异步函数。这种情况下,组件挂载会暂停,直到异步函数执行完成。 -
最后,调用
finishComponentSetup
方法完成组件的挂载。这个方法主要做了以下几件事:- 调用组件的
beforeCreate
生命周期钩子。 - 创建组件的响应式数据对象。
- 调用组件的
created
生命周期钩子。 - 调用组件的
render
方法生成虚拟DOM。 - 调用组件的
beforeMount
生命周期钩子。 - 将组件的虚拟DOM挂载到父组件的DOM节点上。
- 调用组件的
mounted
生命周期钩子。
- 调用组件的
总结
Vue3中组件挂载是一个复杂的过程,涉及到组件实例的创建、状态的初始化、模板的编译、虚拟DOM的生成、组件的渲染等多个步骤。通过对mountComponent
方法的源码解析,我们深入理解了Vue3组件挂载的机制,并掌握了组件挂载过程中需要注意的细节和优化技巧。