处理Fragment

碎片类型的VNode。

  1. // 处理Fragment
  2. const processFragment = (
  3. n1,
  4. n2,
  5. container,
  6. anchor,
  7. parentComponent,
  8. parentSuspense,
  9. isSVG,
  10. optimized
  11. ) => {
  12. const fragmentStartAnchor = (n2.el = n1 ? n1.el : hostCreateText(''))
  13. const fragmentEndAnchor = (n2.anchor = n1
  14. ? n1.anchor
  15. : hostCreateText(''))
  16. let { patchFlag, dynamicChildren } = n2
  17. if (patchFlag > 0) {
  18. optimized = true
  19. }
  20. if (n1 == null) {
  21. // 初始化挂载
  22. hostInsert(fragmentStartAnchor, container, anchor)
  23. hostInsert(fragmentEndAnchor, container, anchor)
  24. // a fragment can only have array children
  25. // since they are either generated by the compiler, or implicitly created
  26. // from arrays.
  27. // 挂载子节点,这里只能是数组的子集
  28. mountChildren(
  29. n2.children,
  30. container,
  31. fragmentEndAnchor,
  32. parentComponent,
  33. parentSuspense,
  34. isSVG,
  35. optimized
  36. )
  37. } else {
  38. // 更新Fragment
  39. if (
  40. patchFlag > 0 &&
  41. patchFlag & 64 /* STABLE_FRAGMENT */ &&
  42. dynamicChildren &&
  43. // #2715 the previous fragment could've been a BAILed one as a result
  44. // of renderSlot() with no valid children
  45. n1.dynamicChildren
  46. ) {
  47. // a stable fragment (template root or <template v-for>) doesn't need to
  48. // patch children order, but it may contain dynamicChildren.
  49. // 稳定片段(template root或<template v-for>)不需要
  50. // 更新整个block,内部会遍历patch
  51. patchBlockChildren(
  52. n1.dynamicChildren,
  53. dynamicChildren,
  54. container,
  55. parentComponent,
  56. parentSuspense,
  57. isSVG
  58. )
  59. if (parentComponent && parentComponent.type.__hmrId) {
  60. traverseStaticChildren(n1, n2)
  61. } else if (
  62. // #2080 if the stable fragment has a key, it's a <template v-for> that may
  63. // get moved around. Make sure all root level vnodes inherit el.
  64. // #2134 or if it's a component root, it may also get moved around
  65. // as the component is being moved.
  66. n2.key != null ||
  67. (parentComponent && n2 === parentComponent.subTree)
  68. )
  69. } else {
  70. // keyed / unkeyed, or manual fragments.
  71. // for keyed & unkeyed, since they are compiler generated from v-for,
  72. // each child is guaranteed to be a block so the fragment will never
  73. // have dynamicChildren.
  74. // 更新子节点,遍历patch
  75. patchChildren(
  76. n1,
  77. n2,
  78. container,
  79. fragmentEndAnchor,
  80. parentComponent,
  81. parentSuspense,
  82. isSVG,
  83. optimized
  84. )
  85. }
  86. }
  87. }

总结:

  1. 新增:
    1. 创建 FragmentStart,创建 FragmentEnd
    2. 挂载所有子节点 mountChildren
  2. 更新:
    1. 有动态收集的子节点, patchBlockChildren
    2. 更新子节点,patchChildren