2019-05-28 10:28:25 +08:00
|
|
|
import { isFunction } from '@vue/shared'
|
|
|
|
|
2019-05-25 23:51:20 +08:00
|
|
|
export const Fragment = Symbol('Fragment')
|
|
|
|
export const Text = Symbol('Text')
|
|
|
|
export const Empty = Symbol('Empty')
|
2018-09-19 23:35:38 +08:00
|
|
|
|
2019-05-25 23:51:20 +08:00
|
|
|
type VNodeTypes =
|
|
|
|
| string
|
|
|
|
| Function
|
|
|
|
| typeof Fragment
|
|
|
|
| typeof Text
|
|
|
|
| typeof Empty
|
2018-09-19 23:35:38 +08:00
|
|
|
|
2019-05-25 23:51:20 +08:00
|
|
|
export type VNodeChild = VNode | string | number | null
|
|
|
|
export interface VNodeChildren extends Array<VNodeChildren | VNodeChild> {}
|
2018-10-13 07:49:41 +08:00
|
|
|
|
2019-05-25 23:51:20 +08:00
|
|
|
export interface VNode {
|
2019-05-26 15:19:44 +08:00
|
|
|
el: any
|
2019-05-27 13:48:40 +08:00
|
|
|
anchor: any // fragment anchor
|
2019-05-25 23:51:20 +08:00
|
|
|
type: VNodeTypes
|
|
|
|
props: { [key: string]: any } | null
|
|
|
|
key: string | number | null
|
|
|
|
children: string | VNodeChildren | null
|
|
|
|
patchFlag: number | null
|
|
|
|
dynamicProps: string[] | null
|
|
|
|
dynamicChildren: VNode[] | null
|
2018-10-13 07:49:41 +08:00
|
|
|
}
|
|
|
|
|
2019-05-27 13:48:40 +08:00
|
|
|
const blockStack: (VNode[] | null)[] = []
|
2018-09-19 23:35:38 +08:00
|
|
|
|
2019-05-25 23:51:20 +08:00
|
|
|
// open block
|
2019-05-27 13:48:40 +08:00
|
|
|
export function openBlock(disableTrackng?: boolean) {
|
|
|
|
blockStack.push(disableTrackng ? null : [])
|
2019-05-25 23:51:20 +08:00
|
|
|
}
|
2018-10-13 07:49:41 +08:00
|
|
|
|
2019-05-25 23:51:20 +08:00
|
|
|
let shouldTrack = true
|
2018-10-13 07:49:41 +08:00
|
|
|
|
2019-05-25 23:51:20 +08:00
|
|
|
// block
|
|
|
|
export function createBlock(
|
|
|
|
type: VNodeTypes,
|
|
|
|
props?: { [key: string]: any } | null,
|
|
|
|
children?: any,
|
|
|
|
patchFlag?: number,
|
|
|
|
dynamicProps?: string[]
|
|
|
|
): VNode {
|
|
|
|
// avoid a block with optFlag tracking itself
|
|
|
|
shouldTrack = false
|
|
|
|
const vnode = createVNode(type, props, children, patchFlag, dynamicProps)
|
|
|
|
shouldTrack = true
|
2019-05-27 13:48:40 +08:00
|
|
|
const trackedNodes = blockStack.pop()
|
|
|
|
vnode.dynamicChildren =
|
|
|
|
trackedNodes && trackedNodes.length ? trackedNodes : null
|
2019-05-25 23:51:20 +08:00
|
|
|
// a block is always going to be patched
|
|
|
|
trackDynamicNode(vnode)
|
|
|
|
return vnode
|
2018-10-13 01:42:19 +08:00
|
|
|
}
|
|
|
|
|
2019-05-25 23:51:20 +08:00
|
|
|
// element
|
|
|
|
export function createVNode(
|
|
|
|
type: VNodeTypes,
|
|
|
|
props: { [key: string]: any } | null = null,
|
|
|
|
children: any = null,
|
|
|
|
patchFlag: number | null = null,
|
|
|
|
dynamicProps: string[] | null = null
|
|
|
|
): VNode {
|
|
|
|
const vnode: VNode = {
|
|
|
|
type,
|
|
|
|
props,
|
|
|
|
key: props && props.key,
|
|
|
|
children,
|
2019-05-27 13:48:40 +08:00
|
|
|
el: null,
|
|
|
|
anchor: null,
|
2019-05-25 23:51:20 +08:00
|
|
|
patchFlag,
|
|
|
|
dynamicProps,
|
|
|
|
dynamicChildren: null
|
2018-09-19 23:35:38 +08:00
|
|
|
}
|
2019-05-28 10:28:25 +08:00
|
|
|
if (shouldTrack && (patchFlag != null || isFunction(type))) {
|
2019-05-25 23:51:20 +08:00
|
|
|
trackDynamicNode(vnode)
|
2018-09-25 07:11:14 +08:00
|
|
|
}
|
2019-05-25 23:51:20 +08:00
|
|
|
return vnode
|
|
|
|
}
|
2018-09-19 23:35:38 +08:00
|
|
|
|
2019-05-25 23:51:20 +08:00
|
|
|
function trackDynamicNode(vnode: VNode) {
|
|
|
|
const currentBlockDynamicNodes = blockStack[blockStack.length - 1]
|
2019-05-27 13:48:40 +08:00
|
|
|
if (currentBlockDynamicNodes != null) {
|
2019-05-25 23:51:20 +08:00
|
|
|
currentBlockDynamicNodes.push(vnode)
|
2018-09-19 23:35:38 +08:00
|
|
|
}
|
2019-05-25 23:51:20 +08:00
|
|
|
}
|
2018-09-19 23:35:38 +08:00
|
|
|
|
2019-05-25 23:51:20 +08:00
|
|
|
export function cloneVNode(vnode: VNode): VNode {
|
|
|
|
// TODO
|
2019-05-26 15:19:44 +08:00
|
|
|
return vnode
|
2019-05-25 23:51:20 +08:00
|
|
|
}
|