]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
feat(runtime-core): support creating vnode from existing vnode
authorEvan You <yyx990803@gmail.com>
Wed, 1 Jul 2020 23:48:01 +0000 (19:48 -0400)
committerEvan You <yyx990803@gmail.com>
Wed, 1 Jul 2020 23:48:01 +0000 (19:48 -0400)
This allows passing vnode around with curried props and use it in
places where VNodeType is expected, e.g. `<component :is=""/>`

packages/runtime-core/__tests__/vnode.spec.ts
packages/runtime-core/src/vnode.ts

index 3573f4a3e24b237d8430ee7baadb2b9bb4c97a7e..dedd0f90e90d40a1b7c55e543d863bae4c3af620 100644 (file)
@@ -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)
index 35b48b6899e35786ce88581ac394a3eede42c23b..f5ff1cdc362753e8e650383046ed32aceb83215c 100644 (file)
@@ -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<T, U>(
   vnode: VNode<T, U>,
-  extraProps?: Data & VNodeProps
+  extraProps?: Data & VNodeProps | null,
+  children?: unknown
 ): VNode<T, U> {
   const props = extraProps
     ? vnode.props
@@ -415,7 +420,7 @@ export function cloneVNode<T, U>(
     : vnode.props
   // This is intentionally NOT using spread or extend to avoid the runtime
   // key enumeration cost.
-  return {
+  const cloned: VNode<T, U> = {
     __v_isVNode: true,
     __v_skip: true,
     type: vnode.type,
@@ -452,6 +457,10 @@ export function cloneVNode<T, U>(
     el: vnode.el,
     anchor: vnode.anchor
   }
+  if (children) {
+    normalizeChildren(cloned, children)
+  }
+  return cloned
 }
 
 /**