diff --git a/packages/runtime-core/__tests__/vnode.spec.ts b/packages/runtime-core/__tests__/vnode.spec.ts index 2e0eee1f280..b3f4222e683 100644 --- a/packages/runtime-core/__tests__/vnode.spec.ts +++ b/packages/runtime-core/__tests__/vnode.spec.ts @@ -50,6 +50,12 @@ describe('vnode', () => { expect(vnode.type).toBe(Comment) }) + test('show warn when create with void element', () => { + const vnode = createVNode('img', null, createVNode('p')) + expect("don't render child nodes in a void element").toHaveBeenWarned() + expect(vnode.type).toBe('img') + }) + test('create from an existing vnode', () => { const vnode1 = createVNode('p', { id: 'foo' }) const vnode2 = createVNode(vnode1, { class: 'bar' }, 'baz') diff --git a/packages/runtime-core/src/vnode.ts b/packages/runtime-core/src/vnode.ts index 30200789be8..bccfb76a91b 100644 --- a/packages/runtime-core/src/vnode.ts +++ b/packages/runtime-core/src/vnode.ts @@ -9,6 +9,7 @@ import { isObject, isOn, isString, + isVoidTag, normalizeClass, normalizeStyle, } from '@vue/shared' @@ -618,6 +619,17 @@ function _createVNode( ? ShapeFlags.FUNCTIONAL_COMPONENT : 0 + if ( + __DEV__ && + shapeFlag & ShapeFlags.ELEMENT && + isVoidTag(type as string) && + children != null + ) { + warn( + `don't render child nodes in a void element <${type as string} />, it may cause unexpected behavior`, + ) + } + if (__DEV__ && shapeFlag & ShapeFlags.STATEFUL_COMPONENT && isProxy(type)) { type = toRaw(type) warn(