]> git.ipfire.org Git - thirdparty/vuejs/core.git/commitdiff
fix(compiler-vapor): treat template v-for with single component child as component
authordaiwei <daiwei521@126.com>
Wed, 17 Sep 2025 01:25:54 +0000 (09:25 +0800)
committerdaiwei <daiwei521@126.com>
Wed, 17 Sep 2025 01:25:54 +0000 (09:25 +0800)
packages/compiler-vapor/__tests__/transforms/__snapshots__/vFor.spec.ts.snap
packages/compiler-vapor/__tests__/transforms/vFor.spec.ts
packages/compiler-vapor/src/transforms/vFor.ts

index 2d6def4e1276ecf119b41b956157a8aad2a443a3..87d9833a9c537ea955a10b5f1517890329bab4eb 100644 (file)
@@ -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("<div>item</div>", true)
index 7357ad84fefafef4805bfbeb57054f4724d9b6db..f79bec89ddaed2501f6c6cf5807252d14c1bccaf 100644 (file)
@@ -368,4 +368,24 @@ describe('compiler: v-for', () => {
       index: undefined,
     })
   })
+
+  test('v-for on component', () => {
+    const { code, ir } = compileWithVFor(
+      `<Comp v-for="item in list">{{item}}</Comp>`,
+    )
+    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(
+      `<template v-for="item in list"><Comp>{{item}}</Comp></template>`,
+    )
+    expect(code).matchSnapshot()
+    expect(
+      (ir.block.dynamic.children[0].operation as ForIRNode).component,
+    ).toBe(true)
+  })
 })
index d4cf42dbd55b9b9e3e23d8f44019cd901a475dd6..c239075aaead9b09eb69f576b0732cd510926eec 100644 (file)
@@ -47,7 +47,13 @@ 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
+    (node.tag === 'template' &&
+      node.children.length === 1 &&
+      node.children[0].type === 1 &&
+      node.children[0].tagType === ElementTypes.COMPONENT)
   context.node = node = wrapTemplate(node, ['for'])
   context.dynamic.flags |= DynamicFlag.NON_TEMPLATE | DynamicFlag.INSERT
   const id = context.reference()