当前位置:   article > 正文

vue3中patch函数(处理vnode)位运算,以及创建vnode的时做了什么_vue3 patch

vue3 patch

patch函数介绍

patch函数用来挂载和更新节点,当节点发生改变,对比旧节点与新节点的不同,采用不同的更新方式。

patch通过对vnode的type进行判断当前是什么类型节点。

下面就然我们看看主要判断逻辑:

  1. const { type, shapeFlag } = n2
  2. //根据新节点的 type 类型,调用不同的处理方法;这里大部分方法名都是以 process 开头,意为加工、处理对应元素
  3. switch (type) {
  4. // 文本节点
  5. case Text:
  6. processText(n1, n2, container, anchor)
  7. break
  8. // 注释节点
  9. case Comment:
  10. processCommentNode(n1, n2, container, anchor)
  11. break
  12. // 静态节点
  13. case Static:
  14. if (n1 == null) {
  15. mountStaticNode(n2, container, anchor, isSVG)
  16. } else if (__DEV__) {
  17. patchStaticNode(n1, n2, container, isSVG)
  18. }
  19. break
  20. // 多根节点
  21. case Fragment:
  22. processFragment(
  23. n1,
  24. n2,
  25. container,
  26. anchor,
  27. parentComponent,
  28. parentSuspense,
  29. isSVG,
  30. slotScopeIds,
  31. optimized
  32. )
  33. break
  34. default:
  35. // 元素
  36. if (shapeFlag & ShapeFlags.ELEMENT) {
  37. processElement(
  38. n1,
  39. n2,
  40. container,
  41. anchor,
  42. parentComponent,
  43. parentSuspense,
  44. isSVG,
  45. slotScopeIds,
  46. optimized
  47. )
  48. // 组件
  49. } else if (shapeFlag & ShapeFlags.COMPONENT) {
  50. processComponent(
  51. n1,
  52. n2,
  53. container,
  54. anchor,
  55. parentComponent,
  56. parentSuspense,
  57. isSVG,
  58. slotScopeIds,
  59. optimized
  60. )
  61. // 传送节点
  62. } else if (shapeFlag & ShapeFlags.TELEPORT) {
  63. ;(type as typeof TeleportImpl).process(
  64. n1 as TeleportVNode,
  65. n2 as TeleportVNode,
  66. container,
  67. anchor,
  68. parentComponent,
  69. parentSuspense,
  70. isSVG,
  71. slotScopeIds,
  72. optimized,
  73. internals
  74. )
  75. // 异步类组件
  76. } else if (__FEATURE_SUSPENSE__ && shapeFlag & ShapeFlags.SUSPENSE) {
  77. ;(type as typeof SuspenseImpl).process(
  78. n1,
  79. n2,
  80. container,
  81. anchor,
  82. parentComponent,
  83. parentSuspense,
  84. isSVG,
  85. slotScopeIds,
  86. optimized,
  87. internals
  88. )
  89. } else if (__DEV__) {
  90. warn('Invalid VNode type:', type, `(${typeof type})`)
  91. }
  92. }

case 条件不用多说了,主要是default 部分的判断。首先从vnode中结构出shapeFlag,然后利用此属性和其他属性进行与运算。判断当前节点类型,然后进行不同的操作。

shapeFlag在创建vnode时也就是createVNode时,进行了赋值操作。如下

  1. const shapeFlag = isString(type)
  2. ? ShapeFlags.ELEMENT
  3. : __FEATURE_SUSPENSE__ && isSuspense(type)
  4. ? ShapeFlags.SUSPENSE
  5. : isTeleport(type)
  6. ? ShapeFlags.TELEPORT
  7. : isObject(type)
  8. ? ShapeFlags.STATEFUL_COMPONENT
  9. : isFunction(type)
  10. ? ShapeFlags.FUNCTIONAL_COMPONENT
  11. : 0

然后执行 createBaseVNode函数,其中如果有children,给shapeFlag重新赋值, 最终返回vnode

  1. // 初始化为needFullChildrenNormalization为true
  2. if (needFullChildrenNormalization) {
  3. normalizeChildren(vnode, children)
  4. // normalize suspense children
  5. if (__FEATURE_SUSPENSE__ && shapeFlag & ShapeFlags.SUSPENSE) {
  6. ;(type as typeof SuspenseImpl).normalize(vnode)
  7. }
  8. } else if (children) {
  9. // TEXT_CHILDREN = 1 << 3, // 8
  10. // ARRAY_CHILDREN = 1 << 4, // 16
  11. vnode.shapeFlag |= isString(children)
  12. ? ShapeFlags.TEXT_CHILDREN
  13. : ShapeFlags.ARRAY_CHILDREN
  14. }
  15. export function normalizeChildren(vnode: VNode, children: unknown) {
  16. let type = 0
  17. const { shapeFlag } = vnode
  18. if (children == null) {
  19. children = null
  20. } else if (isArray(children)) {
  21. type = ShapeFlags.ARRAY_CHILDREN // ARRAY_CHILDREN = 1 << 4, // 16
  22. } else if (typeof children === 'object') {
  23. if (shapeFlag & (ShapeFlags.ELEMENT | ShapeFlags.TELEPORT)) {
  24. } else {
  25. type = ShapeFlags.SLOTS_CHILDREN // SLOTS_CHILDREN = 1 << 5, // 32
  26. }
  27. } else if (isFunction(children)) {
  28. children = { default: children, _ctx: currentRenderingInstance }
  29. type = ShapeFlags.SLOTS_CHILDREN //SLOTS_CHILDREN = 1 << 5, // 32
  30. } else {
  31. children = String(children)
  32. // force teleport children to array so it can be moved around
  33. if (shapeFlag & ShapeFlags.TELEPORT) {
  34. type = ShapeFlags.ARRAY_CHILDREN // ARRAY_CHILDREN = 1 << 4, // 16
  35. children = [createTextVNode(children as string)]
  36. } else {
  37. type = ShapeFlags.TEXT_CHILDREN // TEXT_CHILDREN = 1 << 3, // 8
  38. }
  39. }
  40. vnode.children = children as VNodeNormalizedChildren
  41. vnode.shapeFlag |= type
  42. }

这里的|=或运算并赋值。 如果children是字符串则赋值9,否则赋值17。后边会根据此值进行与运算进行不同节点的处理。

大家也能明白这是什么意思,这里就讲讲ShapeFlags枚举,如下代码:大致明白就是定义属性并赋值。<< 这个双箭头代表左移然后低位补0,注意:它相对于二进制进行操作,例如 1==>0001

1<<1==>0010。

  1. export const enum ShapeFlags {
  2. ELEMENT = 1,
  3. FUNCTIONAL_COMPONENT = 1 << 1, //2
  4. STATEFUL_COMPONENT = 1 << 2, //4
  5. TEXT_CHILDREN = 1 << 3, // 8
  6. ARRAY_CHILDREN = 1 << 4, // 16
  7. SLOTS_CHILDREN = 1 << 5, // 32
  8. TELEPORT = 1 << 6, // 64
  9. SUSPENSE = 1 << 7, //128
  10. COMPONENT_SHOULD_KEEP_ALIVE = 1 << 8, // 256
  11. COMPONENT_KEPT_ALIVE = 1 << 9, // 512
  12. COMPONENT = ShapeFlags.STATEFUL_COMPONENT | ShapeFlags.FUNCTIONAL_COMPONENT
  13. }

再回到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时会赋值。

  1. default:
  2. // 元素
  3. if (shapeFlag & ShapeFlags.ELEMENT) {
  4. processElement(
  5. n1,
  6. n2,
  7. container,
  8. anchor,
  9. parentComponent,
  10. parentSuspense,
  11. isSVG,
  12. slotScopeIds,
  13. optimized
  14. )
  15. // 组件
  16. } else if (shapeFlag & ShapeFlags.COMPONENT) {
  17. processComponent(
  18. n1,
  19. n2,
  20. container,
  21. anchor,
  22. parentComponent,
  23. parentSuspense,
  24. isSVG,
  25. slotScopeIds,
  26. optimized
  27. )
  28. // 传送节点
  29. } else if (shapeFlag & ShapeFlags.TELEPORT) {
  30. ;(type as typeof TeleportImpl).process(
  31. n1 as TeleportVNode,
  32. n2 as TeleportVNode,
  33. container,
  34. anchor,
  35. parentComponent,
  36. parentSuspense,
  37. isSVG,
  38. slotScopeIds,
  39. optimized,
  40. internals
  41. )
  42. // 异步类组件
  43. } else if (__FEATURE_SUSPENSE__ && shapeFlag & ShapeFlags.SUSPENSE) {
  44. ;(type as typeof SuspenseImpl).process(
  45. n1,
  46. n2,
  47. container,
  48. anchor,
  49. parentComponent,
  50. parentSuspense,
  51. isSVG,
  52. slotScopeIds,
  53. optimized,
  54. internals
  55. )
  56. } else if (__DEV__) {
  57. warn('Invalid VNode type:', type, `(${typeof type})`)
  58. }

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop】
推荐阅读
相关标签
  

闽ICP备14008679号