functionsetupBlock(vnode: VNode){// save current block children on the block vnode
vnode.dynamicChildren=isBlockTreeEnabled>0?currentBlock||(EMPTY_ARRasany):null// close block
closeBlock()// a block is always going to be patched, so track it as a child of its
// parent block
// 这个时候的currentBlock已经是它前一个了,也就是父节点的
if(isBlockTreeEnabled>0&¤tBlock){currentBlock.push(vnode)}returnvnode}
functioncreateBaseVNode(type:VNodeTypes|ClassComponent|typeofNULL_DYNAMIC_COMPONENT,props:(Data&VNodeProps)|null=null,children: unknown=null,patchFlag=0,dynamicProps: string[]|null=null,shapeFlag=type===Fragment?0 : ShapeFlags.ELEMENT,isBlockNode=false,needFullChildrenNormalization=false){constvnode={// ....vnode的初始对象
// 。。。
}asVNodeif(needFullChildrenNormalization){normalizeChildren(vnode,children)// normalize suspense children
if(__FEATURE_SUSPENSE__&&shapeFlag&ShapeFlags.SUSPENSE){;(typeastypeofSuspenseImpl).normalize(vnode)}}elseif(children){// compiled element vnode - if children is passed, only possible types are
// string or Array.
vnode.shapeFlag|=isString(children)?ShapeFlags.TEXT_CHILDREN : ShapeFlags.ARRAY_CHILDREN}// track vnode for block tree
if(isBlockTreeEnabled>0&&// avoid a block node from tracking itself
!isBlockNode&&// has current parent block
currentBlock&&// presence of a patch flag indicates this node needs patching on updates.
// component nodes also should always be patched, because even if the
// component doesn't need to update, it needs to persist the instance on to
// the next vnode so that it can be properly unmounted later.
(vnode.patchFlag>0||shapeFlag&ShapeFlags.COMPONENT)&&// the EVENTS flag is only for hydration and if it is the only flag, the
// vnode should not be considered dynamic due to handler caching.
vnode.patchFlag!==PatchFlags.HYDRATE_EVENTS){currentBlock.push(vnode)}// 兼容vue2代码
if(__COMPAT__){convertLegacyVModelProps(vnode)defineLegacyVNodeProperties(vnode)}returnvnode}
if(isVNode(type)){// createVNode receiving an existing vnode. This happens in cases like
// <component :is="vnode"/>
// #2078 make sure to merge refs during the clone instead of overwriting it
// 克隆vnode, 内部ref进行合并
constcloned=cloneVNode(type,props,true/* mergeRef: true */)// 子节点初始化
if(children){normalizeChildren(cloned,children)}//
if(isBlockTreeEnabled>0&&!isBlockNode&¤tBlock){if(cloned.shapeFlag&ShapeFlags.COMPONENT){currentBlock[currentBlock.indexOf(type)]=cloned}else{currentBlock.push(cloned)}}// 这里把patchFlag进行标记,后续跳过diff优化
cloned.patchFlag|=PatchFlags.BAILreturncloned}
如果type是class组件 🔗
type重新赋值
1
2
3
4
// class component normalization.
if(isClassComponent(type)){type=type.__vccOpts}
存在属性 🔗
存在class或者style属性时
进行初始化计算, 这里把class进行了拼接、style进行了拼接
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// class & style normalization.
if(props){// for reactive or proxy objects, we need to clone it to enable mutation.
props=guardReactiveProps(props)!let{class:klass,style}=propsif(klass&&!isString(klass)){props.class=normalizeClass(klass)}if(isObject(style)){// reactive state objects need to be cloned since they are likely to be
// mutated
if(isProxy(style)&&!isArray(style)){style=extend({},style)}props.style=normalizeStyle(style)}}
最后shapeFlag进行重新赋值为位值 🔗
缩减字符长度
1
2
3
4
5
6
7
8
9
10
11
12
// encode the vnode type information into a bitmap
constshapeFlag=isString(type)?ShapeFlags.ELEMENT : __FEATURE_SUSPENSE__&&isSuspense(type)?ShapeFlags.SUSPENSE : isTeleport(type)?ShapeFlags.TELEPORT : isObject(type)?ShapeFlags.STATEFUL_COMPONENT : isFunction(type)?ShapeFlags.FUNCTIONAL_COMPONENT : 0