diff --git a/packages/components/slot/__tests__/only-child.test.tsx b/packages/components/slot/__tests__/only-child.test.tsx index fe894ed3ee..9664c88f62 100644 --- a/packages/components/slot/__tests__/only-child.test.tsx +++ b/packages/components/slot/__tests__/only-child.test.tsx @@ -119,7 +119,7 @@ describe('ElOnlyChild', () => { await nextTick() expect(debugWarn).toHaveBeenCalledTimes(1) - expect(wrapper.text()).toBe('') + expect(wrapper.text()).toBe(AXIOM) }) it('should render nothing when no children provided', async () => { @@ -129,4 +129,12 @@ describe('ElOnlyChild', () => { expect(debugWarn).not.toHaveBeenCalled() expect(wrapper.text()).toBe('') }) + + it('should warns about having multiple children', async () => { + wrapper = createComponent(() => [h(Fragment, null, [AXIOM, AXIOM])]) + await nextTick() + + expect(debugWarn).toHaveBeenCalledTimes(1) + expect(wrapper.text()).toBe(AXIOM) + }) }) diff --git a/packages/components/slot/src/only-child.tsx b/packages/components/slot/src/only-child.tsx index 2f36f3164d..d005d412f6 100644 --- a/packages/components/slot/src/only-child.tsx +++ b/packages/components/slot/src/only-child.tsx @@ -28,17 +28,15 @@ export const OnlyChild = defineComponent({ return () => { const defaultSlot = slots.default?.(attrs) if (!defaultSlot) return null + const [firstLegitNode, length] = findFirstLegitChild(defaultSlot) - if (defaultSlot.length > 1) { - debugWarn(NAME, 'requires exact only one valid child.') - return null - } - - const firstLegitNode = findFirstLegitChild(defaultSlot) if (!firstLegitNode) { debugWarn(NAME, 'no valid child node found') return null } + if (length > 1) { + debugWarn(NAME, 'requires exact only one valid child.') + } return withDirectives(cloneVNode(firstLegitNode!, attrs), [ [forwardRefDirective], @@ -47,9 +45,13 @@ export const OnlyChild = defineComponent({ }, }) -function findFirstLegitChild(node: VNode[] | undefined): VNode | null { - if (!node) return null +function findFirstLegitChild( + node: VNode[] | undefined +): [VNode | null, number] { + if (!node) return [null, 0] const children = node as VNode[] + const len = children.filter((c) => c.type !== Comment).length + for (const child of children) { /** * when user uses h(Fragment, [text]) to render plain string, @@ -62,16 +64,16 @@ function findFirstLegitChild(node: VNode[] | undefined): VNode | null { continue case Text: case 'svg': - return wrapTextContent(child) + return [wrapTextContent(child), len] case Fragment: return findFirstLegitChild(child.children as VNode[]) default: - return child + return [child, len] } } - return wrapTextContent(child) + return [wrapTextContent(child), len] } - return null + return [null, 0] } function wrapTextContent(s: string | VNode) {