赞
踩
patch函数用来挂载和更新节点,当节点发生改变,对比旧节点与新节点的不同,采用不同的更新方式。
patch通过对vnode的type进行判断当前是什么类型节点。
下面就然我们看看主要判断逻辑:
- const { type, shapeFlag } = n2
- //根据新节点的 type 类型,调用不同的处理方法;这里大部分方法名都是以 process 开头,意为加工、处理对应元素
- switch (type) {
- // 文本节点
- case Text:
- processText(n1, n2, container, anchor)
- break
- // 注释节点
- case Comment:
- processCommentNode(n1, n2, container, anchor)
- break
- // 静态节点
- case Static:
- if (n1 == null) {
- mountStaticNode(n2, container, anchor, isSVG)
- } else if (__DEV__) {
- patchStaticNode(n1, n2, container, isSVG)
- }
- break
- // 多根节点
- case Fragment:
- processFragment(
- n1,
- n2,
- container,
- anchor,
- parentComponent,
- parentSuspense,
- isSVG,
- slotScopeIds,
- optimized
- )
- break
- default:
- // 元素
- if (shapeFlag & ShapeFlags.ELEMENT) {
- processElement(
- n1,
- n2,
- container,
- anchor,
- parentComponent,
- parentSuspense,
- isSVG,
- slotScopeIds,
- optimized
- )
- // 组件
- } else if (shapeFlag & ShapeFlags.COMPONENT) {
- processComponent(
- n1,
- n2,
- container,
- anchor,
- parentComponent,
- parentSuspense,
- isSVG,
- slotScopeIds,
- optimized
- )
- // 传送节点
- } else if (shapeFlag & ShapeFlags.TELEPORT) {
- ;(type as typeof TeleportImpl).process(
- n1 as TeleportVNode,
- n2 as TeleportVNode,
- container,
- anchor,
- parentComponent,
- parentSuspense,
- isSVG,
- slotScopeIds,
- optimized,
- internals
- )
- // 异步类组件
- } else if (__FEATURE_SUSPENSE__ && shapeFlag & ShapeFlags.SUSPENSE) {
- ;(type as typeof SuspenseImpl).process(
- n1,
- n2,
- container,
- anchor,
- parentComponent,
- parentSuspense,
- isSVG,
- slotScopeIds,
- optimized,
- internals
- )
- } else if (__DEV__) {
- warn('Invalid VNode type:', type, `(${typeof type})`)
- }
- }
case 条件不用多说了,主要是default 部分的判断。首先从vnode中结构出shapeFlag,然后利用此属性和其他属性进行与运算。判断当前节点类型,然后进行不同的操作。
shapeFlag在创建vnode时也就是createVNode时,进行了赋值操作。如下
- const shapeFlag = 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
然后执行 createBaseVNode函数,其中如果有children,给shapeFlag重新赋值, 最终返回vnode
-
- // 初始化为needFullChildrenNormalization为true
- if (needFullChildrenNormalization) {
- normalizeChildren(vnode, children)
- // normalize suspense children
- if (__FEATURE_SUSPENSE__ && shapeFlag & ShapeFlags.SUSPENSE) {
- ;(type as typeof SuspenseImpl).normalize(vnode)
- }
- } else if (children) {
-
- // TEXT_CHILDREN = 1 << 3, // 8
- // ARRAY_CHILDREN = 1 << 4, // 16
- vnode.shapeFlag |= isString(children)
- ? ShapeFlags.TEXT_CHILDREN
- : ShapeFlags.ARRAY_CHILDREN
- }
-
-
- export function normalizeChildren(vnode: VNode, children: unknown) {
- let type = 0
- const { shapeFlag } = vnode
- if (children == null) {
- children = null
- } else if (isArray(children)) {
- type = ShapeFlags.ARRAY_CHILDREN // ARRAY_CHILDREN = 1 << 4, // 16
- } else if (typeof children === 'object') {
- if (shapeFlag & (ShapeFlags.ELEMENT | ShapeFlags.TELEPORT)) {
-
- } else {
- type = ShapeFlags.SLOTS_CHILDREN // SLOTS_CHILDREN = 1 << 5, // 32
- }
- } else if (isFunction(children)) {
- children = { default: children, _ctx: currentRenderingInstance }
- type = ShapeFlags.SLOTS_CHILDREN //SLOTS_CHILDREN = 1 << 5, // 32
- } else {
- children = String(children)
- // force teleport children to array so it can be moved around
- if (shapeFlag & ShapeFlags.TELEPORT) {
- type = ShapeFlags.ARRAY_CHILDREN // ARRAY_CHILDREN = 1 << 4, // 16
- children = [createTextVNode(children as string)]
- } else {
- type = ShapeFlags.TEXT_CHILDREN // TEXT_CHILDREN = 1 << 3, // 8
- }
- }
- vnode.children = children as VNodeNormalizedChildren
- vnode.shapeFlag |= type
- }
这里的|=是或运算并赋值。 如果children是字符串则赋值9,否则赋值17。后边会根据此值进行与运算进行不同节点的处理。
大家也能明白这是什么意思,这里就讲讲ShapeFlags枚举,如下代码:大致明白就是定义属性并赋值。<< 这个双箭头代表左移然后低位补0,注意:它相对于二进制进行操作,例如 1==>0001
1<<1==>0010。
- export const enum ShapeFlags {
- ELEMENT = 1,
- FUNCTIONAL_COMPONENT = 1 << 1, //2
- STATEFUL_COMPONENT = 1 << 2, //4
- TEXT_CHILDREN = 1 << 3, // 8
- ARRAY_CHILDREN = 1 << 4, // 16
- SLOTS_CHILDREN = 1 << 5, // 32
- TELEPORT = 1 << 6, // 64
- SUSPENSE = 1 << 7, //128
- COMPONENT_SHOULD_KEEP_ALIVE = 1 << 8, // 256
- COMPONENT_KEPT_ALIVE = 1 << 9, // 512
- COMPONENT = ShapeFlags.STATEFUL_COMPONENT | ShapeFlags.FUNCTIONAL_COMPONENT
- }
再回到patch函数中,如果我们在页面创建了const app = h('div',['12312',count.value]),这里的app就是vnode,其中children就是数组,即shapeFlag=17。const app = h('div',123);shapeFlag=9。
在利用shapeFlag&ShapeFlags.ELEMENT>0 也就是10001&0001=10001==>17,所以条件成立。与其他都为0,所以当前为元素节点。其他节点也是相同的计算,shapeFlag在上边也有讲,在创建vnode时会赋值。
- default:
- // 元素
- if (shapeFlag & ShapeFlags.ELEMENT) {
- processElement(
- n1,
- n2,
- container,
- anchor,
- parentComponent,
- parentSuspense,
- isSVG,
- slotScopeIds,
- optimized
- )
- // 组件
- } else if (shapeFlag & ShapeFlags.COMPONENT) {
- processComponent(
- n1,
- n2,
- container,
- anchor,
- parentComponent,
- parentSuspense,
- isSVG,
- slotScopeIds,
- optimized
- )
- // 传送节点
- } else if (shapeFlag & ShapeFlags.TELEPORT) {
- ;(type as typeof TeleportImpl).process(
- n1 as TeleportVNode,
- n2 as TeleportVNode,
- container,
- anchor,
- parentComponent,
- parentSuspense,
- isSVG,
- slotScopeIds,
- optimized,
- internals
- )
- // 异步类组件
- } else if (__FEATURE_SUSPENSE__ && shapeFlag & ShapeFlags.SUSPENSE) {
- ;(type as typeof SuspenseImpl).process(
- n1,
- n2,
- container,
- anchor,
- parentComponent,
- parentSuspense,
- isSVG,
- slotScopeIds,
- optimized,
- internals
- )
- } else if (__DEV__) {
- warn('Invalid VNode type:', type, `(${typeof type})`)
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。