先大概写一下:
1.创建vnode
2.对vnode进行patch
3.在patch的过程中,如果是component类型,那么会生成子树subtree 然后patchsubtree ,如果是element类型会执行创建el,插入内容,如果子是数组那么遍历去patch
createVNode(normalizeChildren)
|
render(ensureRender生成的)
|
patch(container._vnode,vnode,container)
|
根据类型processComponent/processElement
|
CreateComponentInstance
|
setupInstance
|
setupRenderEffect(setupRenderEffect(instance, initialVNode, container, anchor, parentSuspense, isSVG, optimized))
|
effect(function componentEffect(){
})
| |
If(!instance.isMounted) else
Const subtree=renderComponentRoot(instance)
|
patch(null,subtree,container,…)
processElement
|
n1==null else
| |
mountElement patchElement
|
1.el=vnode.el=createElement
2.if(textChildren) setElementText
if(arrayChildren) mountChildren
|
for(let I = start ;i<chidlren.length;i++
patch(null,child…)
2.hostInsert(el, container, anchor)
----------------------------------------------
2.组件更新引发diff过程
当组件更新时
1. 进入effect的更新逻辑,调用update方法
如果instance中有next, 更新组件vnode节点信息(updateComponentPrerender,更改组件实例的 vnode 指针、更新 props 更新插槽 再把next设为null等一系列操作),生成新的子树,然后进行patch
Patch中,如果新旧不同,就销毁旧节点, 然后根据类型进行process,如果是组件就processComponent,
processComponent如果n1不是null,进入updateComponent,
如果shouldUpdateComponent,就把n2赋给instance的next,手动执行instance.update
如果是元素就processElement
processElement中 如果n1不是null,会进入patchElement逻辑,patchProps更新props,patchChildren更新子节点
子节点可能有三种情况 文本,数组,空
新子节点也可能有三种情况,最复杂的情况是新旧子节点都是数组,会进行一个完整的diff