挂载Element

  1. const mountElement = (
  2. vnode,
  3. container,
  4. anchor,
  5. parentComponent,
  6. parentSuspense,
  7. isSVG,
  8. optimized
  9. ) => {
  10. let el
  11. let vnodeHook
  12. const {
  13. type,
  14. props,
  15. shapeFlag,
  16. transition,
  17. scopeId,
  18. patchFlag,
  19. dirs,
  20. } = vnode
  21. {
  22. // 创建dom节点
  23. el = vnode.el = hostCreateElement(vnode.type, isSVG, props && props.is)
  24. if (shapeFlag & 8 /* TEXT_CHILDREN */) {
  25. hostSetElementText(el, vnode.children)
  26. } else if (shapeFlag & 16 /* ARRAY_CHILDREN */) {
  27. // 处理数组子节点
  28. mountChildren(
  29. vnode.children,
  30. el,
  31. null,
  32. parentComponent,
  33. parentSuspense,
  34. isSVG && type !== 'foreignObject',
  35. optimized || !!vnode.dynamicChildren
  36. )
  37. }
  38. // vnode的props:例如 { id: 'search', type:'button' }
  39. if (props) {
  40. for (const key in props) {
  41. if (!isReservedProp(key)) {
  42. hostPatchProp(
  43. el,
  44. key,
  45. null,
  46. props[key],
  47. isSVG,
  48. vnode.children,
  49. parentComponent,
  50. parentSuspense,
  51. unmountChildren
  52. )
  53. }
  54. }
  55. }
  56. // 设置dom的一些attr属性
  57. setScopeId(el, scopeId, vnode, parentComponent)
  58. }
  59. // 将虚拟节点缓存给dom,且不能被枚举出来。
  60. {
  61. Object.defineProperty(el, '__vnode', {
  62. value: vnode,
  63. enumerable: false,
  64. })
  65. Object.defineProperty(el, '__vueParentComponent', {
  66. value: parentComponent,
  67. enumerable: false,
  68. })
  69. }
  70. // 把创建的 element,插入到节点中
  71. hostInsert(el, container, anchor)
  72. }

总结

  1. 创建一个element,赋值给 vnode.el
  2. 判断子节点类型
    1. 子节点是文本:创建文本
    2. 子节点是数组:执行方法 mountChildren,批量挂载子节点
  3. 设置element的 props
  4. 设置element的 attr 属性
  5. 把创建的element插入到 container