From c9629f26924fcb3c51994549a3013ccc05c1030a Mon Sep 17 00:00:00 2001 From: Evan You Date: Wed, 1 Jul 2020 19:48:01 -0400 Subject: [PATCH] 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. `` --- packages/runtime-core/__tests__/vnode.spec.ts | 14 ++++++++++++++ packages/runtime-core/src/vnode.ts | 15 ++++++++++++--- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/packages/runtime-core/__tests__/vnode.spec.ts b/packages/runtime-core/__tests__/vnode.spec.ts index 3573f4a3..dedd0f90 100644 --- a/packages/runtime-core/__tests__/vnode.spec.ts +++ b/packages/runtime-core/__tests__/vnode.spec.ts @@ -42,6 +42,20 @@ describe('vnode', () => { 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', () => { for (const key of ['', 'a', 0, 1, NaN]) { expect(createVNode('div', { key }).key).toBe(key) diff --git a/packages/runtime-core/src/vnode.ts b/packages/runtime-core/src/vnode.ts index 35b48b68..f5ff1cdc 100644 --- a/packages/runtime-core/src/vnode.ts +++ b/packages/runtime-core/src/vnode.ts @@ -290,7 +290,7 @@ export const createVNode = (__DEV__ : _createVNode) as typeof _createVNode function _createVNode( - type: VNodeTypes | ClassComponent | typeof NULL_DYNAMIC_COMPONENT, + type: VNode | VNodeTypes | ClassComponent | typeof NULL_DYNAMIC_COMPONENT, props: (Data & VNodeProps) | null = null, children: unknown = null, patchFlag: number = 0, @@ -304,6 +304,10 @@ function _createVNode( type = Comment } + if (isVNode(type)) { + return cloneVNode(type, props, children) + } + // class component normalization. if (isFunction(type) && '__vccOpts' in type) { type = type.__vccOpts @@ -406,7 +410,8 @@ function _createVNode( export function cloneVNode( vnode: VNode, - extraProps?: Data & VNodeProps + extraProps?: Data & VNodeProps | null, + children?: unknown ): VNode { const props = extraProps ? vnode.props @@ -415,7 +420,7 @@ export function cloneVNode( : vnode.props // This is intentionally NOT using spread or extend to avoid the runtime // key enumeration cost. - return { + const cloned: VNode = { __v_isVNode: true, __v_skip: true, type: vnode.type, @@ -452,6 +457,10 @@ export function cloneVNode( el: vnode.el, anchor: vnode.anchor } + if (children) { + normalizeChildren(cloned, children) + } + return cloned } /**