mirror of https://github.com/vuejs/core.git
fix(compiler-vapor): treat template v-for with single component child as component (#13914)
This commit is contained in:
parent
b65a6b869e
commit
3b5e13c7eb
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
})
|
||||
})
|
||||
|
|
|
@ -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<ElementNode>,
|
||||
) {
|
||||
): (() => 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
|
||||
)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue