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(
+ `{{item}}`,
+ )
+ 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
+ )
+}