更新Element

更新element节点,主要是更新props和子节点,内部还涉及到动态patch更新。

  1. const patchElement = (
  2. n1,
  3. n2,
  4. parentComponent,
  5. parentSuspense,
  6. isSVG,
  7. optimized
  8. ) => {
  9. const el = (n2.el = n1.el)
  10. let { patchFlag, dynamicChildren, dirs } = n2
  11. patchFlag |= n1.patchFlag & 16 /* FULL_PROPS */
  12. const oldProps = n1.props || EMPTY_OBJ
  13. const newProps = n2.props || EMPTY_OBJ
  14. if (patchFlag > 0) {
  15. if (patchFlag & 16 /* FULL_PROPS */) {
  16. // 更新props
  17. patchProps(
  18. el,
  19. n2,
  20. oldProps,
  21. newProps,
  22. parentComponent,
  23. parentSuspense,
  24. isSVG
  25. )
  26. } else {
  27. // class
  28. if (patchFlag & 2 /* CLASS */) {
  29. if (oldProps.class !== newProps.class) {
  30. // 更新class
  31. hostPatchProp(el, 'class', null, newProps.class, isSVG)
  32. }
  33. }
  34. // style
  35. if (patchFlag & 4 /* STYLE */) {
  36. hostPatchProp(el, 'style', oldProps.style, newProps.style, isSVG)
  37. }
  38. // props
  39. if (patchFlag & 8 /* PROPS */) {
  40. const propsToUpdate = n2.dynamicProps
  41. /**
  42. * propsToUpdate是 onClick | onUpdate:modelValue 这些。
  43. * 示例:<polygon :points="points"></polygon> propsToUpdate === ["points"]
  44. */
  45. for (let i = 0; i < propsToUpdate.length; i++) {
  46. const key = propsToUpdate[i]
  47. const prev = oldProps[key]
  48. const next = newProps[key]
  49. // 这里的next可能是 string number function object boolean
  50. // 比较不同就更新
  51. if (
  52. next !== prev ||
  53. (hostForcePatchProp && hostForcePatchProp(el, key))
  54. ) {
  55. hostPatchProp(
  56. el,
  57. key,
  58. prev,
  59. next,
  60. isSVG,
  61. n1.children,
  62. parentComponent,
  63. parentSuspense,
  64. unmountChildren
  65. )
  66. }
  67. }
  68. }
  69. }
  70. // text
  71. if (patchFlag & 1 /* TEXT */) {
  72. if (n1.children !== n2.children) {
  73. hostSetElementText(el, n2.children)
  74. }
  75. }
  76. }
  77. else if (!optimized && dynamicChildren == null) {
  78. // unoptimized, full diff
  79. patchProps(
  80. el,
  81. n2,
  82. oldProps,
  83. newProps,
  84. parentComponent,
  85. parentSuspense,
  86. isSVG
  87. )
  88. }
  89. // full diff
  90. patchChildren(
  91. n1,
  92. n2,
  93. el,
  94. null,
  95. parentComponent,
  96. parentSuspense,
  97. areChildrenSVG
  98. )
  99. }

总结

主要做了以下几件事情:

  1. 更新 props
  2. 更新 class
  3. 更新 style
  4. 更新 text
  5. 更新子节点 patchChildren