import type { Component } from 'types/component'
|
import type { ComponentOptions } from 'types/options'
|
import type { VNodeComponentOptions, VNodeData } from 'types/vnode'
|
|
/**
|
* @internal
|
*/
|
export default class VNode {
|
tag?: string
|
data: VNodeData | undefined
|
children?: Array<VNode> | null
|
text?: string
|
elm: Node | undefined
|
ns?: string
|
context?: Component // rendered in this component's scope
|
key: string | number | undefined
|
componentOptions?: VNodeComponentOptions
|
componentInstance?: Component // component instance
|
parent: VNode | undefined | null // component placeholder node
|
|
// strictly internal
|
raw: boolean // contains raw HTML? (server only)
|
isStatic: boolean // hoisted static node
|
isRootInsert: boolean // necessary for enter transition check
|
isComment: boolean // empty comment placeholder?
|
isCloned: boolean // is a cloned node?
|
isOnce: boolean // is a v-once node?
|
asyncFactory?: Function // async component factory function
|
asyncMeta: Object | void
|
isAsyncPlaceholder: boolean
|
ssrContext?: Object | void
|
fnContext: Component | void // real context vm for functional nodes
|
fnOptions?: ComponentOptions | null // for SSR caching
|
devtoolsMeta?: Object | null // used to store functional render context for devtools
|
fnScopeId?: string | null // functional scope id support
|
isComponentRootElement?: boolean | null // for SSR directives
|
|
constructor(
|
tag?: string,
|
data?: VNodeData,
|
children?: Array<VNode> | null,
|
text?: string,
|
elm?: Node,
|
context?: Component,
|
componentOptions?: VNodeComponentOptions,
|
asyncFactory?: Function
|
) {
|
this.tag = tag
|
this.data = data
|
this.children = children
|
this.text = text
|
this.elm = elm
|
this.ns = undefined
|
this.context = context
|
this.fnContext = undefined
|
this.fnOptions = undefined
|
this.fnScopeId = undefined
|
this.key = data && data.key
|
this.componentOptions = componentOptions
|
this.componentInstance = undefined
|
this.parent = undefined
|
this.raw = false
|
this.isStatic = false
|
this.isRootInsert = true
|
this.isComment = false
|
this.isCloned = false
|
this.isOnce = false
|
this.asyncFactory = asyncFactory
|
this.asyncMeta = undefined
|
this.isAsyncPlaceholder = false
|
}
|
|
// DEPRECATED: alias for componentInstance for backwards compat.
|
/* istanbul ignore next */
|
get child(): Component | void {
|
return this.componentInstance
|
}
|
}
|
|
export const createEmptyVNode = (text: string = '') => {
|
const node = new VNode()
|
node.text = text
|
node.isComment = true
|
return node
|
}
|
|
export function createTextVNode(val: string | number) {
|
return new VNode(undefined, undefined, undefined, String(val))
|
}
|
|
// optimized shallow clone
|
// used for static nodes and slot nodes because they may be reused across
|
// multiple renders, cloning them avoids errors when DOM manipulations rely
|
// on their elm reference.
|
export function cloneVNode(vnode: VNode): VNode {
|
const cloned = new VNode(
|
vnode.tag,
|
vnode.data,
|
// #7975
|
// clone children array to avoid mutating original in case of cloning
|
// a child.
|
vnode.children && vnode.children.slice(),
|
vnode.text,
|
vnode.elm,
|
vnode.context,
|
vnode.componentOptions,
|
vnode.asyncFactory
|
)
|
cloned.ns = vnode.ns
|
cloned.isStatic = vnode.isStatic
|
cloned.key = vnode.key
|
cloned.isComment = vnode.isComment
|
cloned.fnContext = vnode.fnContext
|
cloned.fnOptions = vnode.fnOptions
|
cloned.fnScopeId = vnode.fnScopeId
|
cloned.asyncMeta = vnode.asyncMeta
|
cloned.isCloned = true
|
return cloned
|
}
|