]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
refactor(runtime-core): make h() support single vnode child (#181)
authorterencez <texvnars@gmail.com>
Thu, 10 Oct 2019 14:17:16 +0000 (22:17 +0800)
committerEvan You <yyx990803@gmail.com>
Thu, 10 Oct 2019 14:17:16 +0000 (10:17 -0400)
packages/runtime-core/__tests__/h.spec.ts
packages/runtime-core/src/h.ts
packages/runtime-core/src/vnode.ts

index b71958d8d642abd7c540fae04606161fabbcaf3a..b55c9f4820b0e9beb024124ad6b8f5aa0d3085b4 100644 (file)
@@ -18,8 +18,12 @@ describe('renderer: h', () => {
     // array
     expect(h('div', ['foo'])).toMatchObject(createVNode('div', null, ['foo']))
     // default slot
+    const Component = { template: '<br />' }
     const slot = () => {}
-    expect(h('div', slot)).toMatchObject(createVNode('div', null, slot))
+    expect(h(Component, slot)).toMatchObject(createVNode(Component, null, slot))
+    // single vnode
+    const vnode = h('div')
+    expect(h('div', vnode)).toMatchObject(createVNode('div', null, [vnode]))
     // text
     expect(h('div', 'foo')).toMatchObject(createVNode('div', null, 'foo'))
   })
@@ -28,20 +32,27 @@ describe('renderer: h', () => {
     // array
     expect(h('div', {}, ['foo'])).toMatchObject(createVNode('div', {}, ['foo']))
     // default slot
+    const Component = { template: '<br />' }
     const slot = () => {}
-    expect(h('div', {}, slot)).toMatchObject(createVNode('div', {}, slot))
+    expect(h(Component, {}, slot)).toMatchObject(
+      createVNode(Component, {}, slot)
+    )
+    // single vnode
+    const vnode = h('div')
+    expect(h('div', {}, vnode)).toMatchObject(createVNode('div', {}, [vnode]))
     // text
     expect(h('div', {}, 'foo')).toMatchObject(createVNode('div', {}, 'foo'))
   })
 
   test('named slots with null props', () => {
+    const Component = { template: '<br />' }
     const slot = () => {}
     expect(
-      h('div', null, {
+      h(Component, null, {
         foo: slot
       })
     ).toMatchObject(
-      createVNode('div', null, {
+      createVNode(Component, null, {
         foo: slot
       })
     )
index 5b32f3b7c6b6b1aa34cadc4ca65b0796acda42c9..eebee3684aed2cd1e1998f9d9c4011b9f3d67740 100644 (file)
@@ -4,7 +4,8 @@ import {
   createVNode,
   VNodeChildren,
   Fragment,
-  Portal
+  Portal,
+  isVNode
 } from './vnode'
 import { isObject, isArray } from '@vue/shared'
 import { Ref } from '@vue/reactivity'
@@ -34,17 +35,19 @@ h('div', {})
 // type + omit props + children
 // Omit props does NOT support named slots
 h('div', []) // array
-h('div', () => {}) // default slot
 h('div', 'foo') // text
+h('div', h('br')) // vnode
+h(Component, () => {}) // default slot
 
 // type + props + children
 h('div', {}, []) // array
-h('div', {}, () => {}) // default slot
-h('div', {}, {}) // named slots
 h('div', {}, 'foo') // text
+h('div', {}, h('br')) // vnode
+h(Component, {}, () => {}) // default slot
+h(Component, {}, {}) // named slots
 
 // named slots without props requires explicit `null` to avoid ambiguity
-h('div', null, {})
+h(Component, null, {})
 **/
 
 export interface RawProps {
@@ -61,6 +64,7 @@ export type RawChildren =
   | string
   | number
   | boolean
+  | VNode
   | VNodeChildren
   | (() => any)
 
@@ -142,6 +146,10 @@ export function h(
 ): VNode {
   if (arguments.length === 2) {
     if (isObject(propsOrChildren) && !isArray(propsOrChildren)) {
+      // single vnode without props
+      if (isVNode(propsOrChildren)) {
+        return createVNode(type, null, [propsOrChildren])
+      }
       // props without children
       return createVNode(type, propsOrChildren)
     } else {
@@ -149,6 +157,9 @@ export function h(
       return createVNode(type, null, propsOrChildren)
     }
   } else {
+    if (isVNode(children)) {
+      children = [children]
+    }
     return createVNode(type, propsOrChildren, children)
   }
 }
index 2229fbcdc313a1538c353a775bec51e887149c71..9abb4476d7145de86c9dce68a96a9c98b334a7fa 100644 (file)
@@ -129,7 +129,7 @@ export function createBlock(
   return vnode
 }
 
-export function isVNode(value: any): boolean {
+export function isVNode(value: any): value is VNode {
   return value ? value._isVNode === true : false
 }