feat(runtime-core): support creating vnode from existing vnode
This allows passing vnode around with curried props and use it in places where VNodeType is expected, e.g. `<component :is=""/>`
This commit is contained in:
parent
359b4a30ca
commit
c9629f2692
@ -42,6 +42,20 @@ describe('vnode', () => {
|
|||||||
expect(vnode.props).toBe(null)
|
expect(vnode.props).toBe(null)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('create from an existing vnode', () => {
|
||||||
|
const vnode1 = createVNode('p', { id: 'foo' })
|
||||||
|
const vnode2 = createVNode(vnode1, { class: 'bar' }, 'baz')
|
||||||
|
expect(vnode2).toMatchObject({
|
||||||
|
type: 'p',
|
||||||
|
props: {
|
||||||
|
id: 'foo',
|
||||||
|
class: 'bar'
|
||||||
|
},
|
||||||
|
children: 'baz',
|
||||||
|
shapeFlag: ShapeFlags.ELEMENT | ShapeFlags.TEXT_CHILDREN
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
test('vnode keys', () => {
|
test('vnode keys', () => {
|
||||||
for (const key of ['', 'a', 0, 1, NaN]) {
|
for (const key of ['', 'a', 0, 1, NaN]) {
|
||||||
expect(createVNode('div', { key }).key).toBe(key)
|
expect(createVNode('div', { key }).key).toBe(key)
|
||||||
|
@ -290,7 +290,7 @@ export const createVNode = (__DEV__
|
|||||||
: _createVNode) as typeof _createVNode
|
: _createVNode) as typeof _createVNode
|
||||||
|
|
||||||
function _createVNode(
|
function _createVNode(
|
||||||
type: VNodeTypes | ClassComponent | typeof NULL_DYNAMIC_COMPONENT,
|
type: VNode | VNodeTypes | ClassComponent | typeof NULL_DYNAMIC_COMPONENT,
|
||||||
props: (Data & VNodeProps) | null = null,
|
props: (Data & VNodeProps) | null = null,
|
||||||
children: unknown = null,
|
children: unknown = null,
|
||||||
patchFlag: number = 0,
|
patchFlag: number = 0,
|
||||||
@ -304,6 +304,10 @@ function _createVNode(
|
|||||||
type = Comment
|
type = Comment
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isVNode(type)) {
|
||||||
|
return cloneVNode(type, props, children)
|
||||||
|
}
|
||||||
|
|
||||||
// class component normalization.
|
// class component normalization.
|
||||||
if (isFunction(type) && '__vccOpts' in type) {
|
if (isFunction(type) && '__vccOpts' in type) {
|
||||||
type = type.__vccOpts
|
type = type.__vccOpts
|
||||||
@ -406,7 +410,8 @@ function _createVNode(
|
|||||||
|
|
||||||
export function cloneVNode<T, U>(
|
export function cloneVNode<T, U>(
|
||||||
vnode: VNode<T, U>,
|
vnode: VNode<T, U>,
|
||||||
extraProps?: Data & VNodeProps
|
extraProps?: Data & VNodeProps | null,
|
||||||
|
children?: unknown
|
||||||
): VNode<T, U> {
|
): VNode<T, U> {
|
||||||
const props = extraProps
|
const props = extraProps
|
||||||
? vnode.props
|
? vnode.props
|
||||||
@ -415,7 +420,7 @@ export function cloneVNode<T, U>(
|
|||||||
: vnode.props
|
: vnode.props
|
||||||
// This is intentionally NOT using spread or extend to avoid the runtime
|
// This is intentionally NOT using spread or extend to avoid the runtime
|
||||||
// key enumeration cost.
|
// key enumeration cost.
|
||||||
return {
|
const cloned: VNode<T, U> = {
|
||||||
__v_isVNode: true,
|
__v_isVNode: true,
|
||||||
__v_skip: true,
|
__v_skip: true,
|
||||||
type: vnode.type,
|
type: vnode.type,
|
||||||
@ -452,6 +457,10 @@ export function cloneVNode<T, U>(
|
|||||||
el: vnode.el,
|
el: vnode.el,
|
||||||
anchor: vnode.anchor
|
anchor: vnode.anchor
|
||||||
}
|
}
|
||||||
|
if (children) {
|
||||||
|
normalizeChildren(cloned, children)
|
||||||
|
}
|
||||||
|
return cloned
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user