diff --git a/packages/compiler-vapor/__tests__/transforms/__snapshots__/vFor.spec.ts.snap b/packages/compiler-vapor/__tests__/transforms/__snapshots__/vFor.spec.ts.snap index 69c695a24..4b1574e5d 100644 --- a/packages/compiler-vapor/__tests__/transforms/__snapshots__/vFor.spec.ts.snap +++ b/packages/compiler-vapor/__tests__/transforms/__snapshots__/vFor.spec.ts.snap @@ -235,6 +235,38 @@ export function render(_ctx) { }" `; +exports[`compiler: v-for > v-for on component 1`] = ` +"import { resolveComponent as _resolveComponent, createComponentWithFallback as _createComponentWithFallback, child as _child, toDisplayString as _toDisplayString, setText as _setText, renderEffect as _renderEffect, createFor as _createFor, template as _template } from 'vue'; +const t0 = _template(" ") + +export function render(_ctx) { + const _component_Comp = _resolveComponent("Comp") + const n0 = _createFor(() => (_ctx.list), (_for_item0) => { + const n3 = _createComponentWithFallback(_component_Comp) + const n2 = _child(n3) + _renderEffect(() => _setText(n2, _toDisplayString(_for_item0.value))) + return [n2, n3] + }, undefined, 2) + return n0 +}" +`; + +exports[`compiler: v-for > v-for on template with single component child 1`] = ` +"import { resolveComponent as _resolveComponent, createComponentWithFallback as _createComponentWithFallback, child as _child, toDisplayString as _toDisplayString, setText as _setText, renderEffect as _renderEffect, createFor as _createFor, template as _template } from 'vue'; +const t0 = _template(" ") + +export function render(_ctx) { + const _component_Comp = _resolveComponent("Comp") + const n0 = _createFor(() => (_ctx.list), (_for_item0) => { + const n3 = _createComponentWithFallback(_component_Comp) + const n2 = _child(n3) + _renderEffect(() => _setText(n2, _toDisplayString(_for_item0.value))) + return [n2, n3] + }, undefined, 2) + return n0 +}" +`; + exports[`compiler: v-for > w/o value 1`] = ` "import { createFor as _createFor, template as _template } from 'vue'; const t0 = _template("
item
", true) diff --git a/packages/compiler-vapor/__tests__/transforms/vFor.spec.ts b/packages/compiler-vapor/__tests__/transforms/vFor.spec.ts index 7357ad84f..f79bec89d 100644 --- a/packages/compiler-vapor/__tests__/transforms/vFor.spec.ts +++ b/packages/compiler-vapor/__tests__/transforms/vFor.spec.ts @@ -368,4 +368,24 @@ describe('compiler: v-for', () => { index: undefined, }) }) + + test('v-for on component', () => { + const { code, ir } = compileWithVFor( + `{{item}}`, + ) + expect(code).matchSnapshot() + expect( + (ir.block.dynamic.children[0].operation as ForIRNode).component, + ).toBe(true) + }) + + test('v-for on template with single component child', () => { + const { code, ir } = compileWithVFor( + ``, + ) + expect(code).matchSnapshot() + expect( + (ir.block.dynamic.children[0].operation as ForIRNode).component, + ).toBe(true) + }) }) diff --git a/packages/compiler-vapor/src/transforms/vFor.ts b/packages/compiler-vapor/src/transforms/vFor.ts index d4cf42dbd..11acd6d22 100644 --- a/packages/compiler-vapor/src/transforms/vFor.ts +++ b/packages/compiler-vapor/src/transforms/vFor.ts @@ -2,6 +2,7 @@ import { type ElementNode, ElementTypes, ErrorCodes, + NodeTypes, type SimpleExpressionNode, createCompilerError, } from '@vue/compiler-dom' @@ -28,7 +29,7 @@ export function processFor( node: ElementNode, dir: VaporDirectiveNode, context: TransformContext, -) { +): (() => void) | undefined { if (!dir.exp) { context.options.onError( createCompilerError(ErrorCodes.X_V_FOR_NO_EXPRESSION, dir.loc), @@ -47,7 +48,10 @@ export function processFor( const keyProp = findProp(node, 'key') const keyProperty = keyProp && propToExpression(keyProp) - const isComponent = node.tagType === ElementTypes.COMPONENT + const isComponent = + node.tagType === ElementTypes.COMPONENT || + // template v-for with a single component child + isTemplateWithSingleComponent(node) context.node = node = wrapTemplate(node, ['for']) context.dynamic.flags |= DynamicFlag.NON_TEMPLATE | DynamicFlag.INSERT const id = context.reference() @@ -87,3 +91,16 @@ export function processFor( } } } + +function isTemplateWithSingleComponent(node: ElementNode): boolean { + if (node.tag !== 'template') return false + + const nonCommentChildren = node.children.filter( + c => c.type !== NodeTypes.COMMENT, + ) + return ( + nonCommentChildren.length === 1 && + nonCommentChildren[0].type === NodeTypes.ELEMENT && + nonCommentChildren[0].tagType === ElementTypes.COMPONENT + ) +}