h.ts 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. export const Fragment = Symbol('Fragment')
  2. export const Text = Symbol('Text')
  3. export const Empty = Symbol('Empty')
  4. type VNodeTypes =
  5. | string
  6. | Function
  7. | typeof Fragment
  8. | typeof Text
  9. | typeof Empty
  10. export type VNodeChild = VNode | string | number | null
  11. export interface VNodeChildren extends Array<VNodeChildren | VNodeChild> {}
  12. export interface VNode {
  13. el: any
  14. type: VNodeTypes
  15. props: { [key: string]: any } | null
  16. key: string | number | null
  17. children: string | VNodeChildren | null
  18. patchFlag: number | null
  19. dynamicProps: string[] | null
  20. dynamicChildren: VNode[] | null
  21. }
  22. const blockStack: (VNode[])[] = []
  23. // open block
  24. export function openBlock() {
  25. blockStack.push([])
  26. }
  27. let shouldTrack = true
  28. // block
  29. export function createBlock(
  30. type: VNodeTypes,
  31. props?: { [key: string]: any } | null,
  32. children?: any,
  33. patchFlag?: number,
  34. dynamicProps?: string[]
  35. ): VNode {
  36. // avoid a block with optFlag tracking itself
  37. shouldTrack = false
  38. const vnode = createVNode(type, props, children, patchFlag, dynamicProps)
  39. shouldTrack = true
  40. vnode.dynamicChildren = blockStack.pop() || null
  41. // a block is always going to be patched
  42. trackDynamicNode(vnode)
  43. return vnode
  44. }
  45. // element
  46. export function createVNode(
  47. type: VNodeTypes,
  48. props: { [key: string]: any } | null = null,
  49. children: any = null,
  50. patchFlag: number | null = null,
  51. dynamicProps: string[] | null = null
  52. ): VNode {
  53. const vnode: VNode = {
  54. el: null,
  55. type,
  56. props,
  57. key: props && props.key,
  58. children,
  59. patchFlag,
  60. dynamicProps,
  61. dynamicChildren: null
  62. }
  63. if (patchFlag != null && shouldTrack) {
  64. trackDynamicNode(vnode)
  65. }
  66. return vnode
  67. }
  68. function trackDynamicNode(vnode: VNode) {
  69. const currentBlockDynamicNodes = blockStack[blockStack.length - 1]
  70. if (currentBlockDynamicNodes) {
  71. currentBlockDynamicNodes.push(vnode)
  72. }
  73. }
  74. export function cloneVNode(vnode: VNode): VNode {
  75. // TODO
  76. return vnode
  77. }