mirror of https://github.com/vuejs/core.git
fix(compiler-core): force dynamic slots when slot referencing scope vars (#9427)
close #9380
This commit is contained in:
parent
15fc75f403
commit
99d54b28b4
|
@ -478,7 +478,10 @@ describe('compiler: transform component slots', () => {
|
|||
})
|
||||
|
||||
test('should only force dynamic slots when actually using scope vars w/ prefixIdentifiers: true', () => {
|
||||
function assertDynamicSlots(template: string, shouldForce: boolean) {
|
||||
function assertDynamicSlots(
|
||||
template: string,
|
||||
expectedPatchFlag?: PatchFlags,
|
||||
) {
|
||||
const { root } = parseWithSlots(template, { prefixIdentifiers: true })
|
||||
let flag: any
|
||||
if (root.children[0].type === NodeTypes.FOR) {
|
||||
|
@ -491,8 +494,8 @@ describe('compiler: transform component slots', () => {
|
|||
.children[0] as ComponentNode
|
||||
flag = (innerComp.codegenNode as VNodeCall).patchFlag
|
||||
}
|
||||
if (shouldForce) {
|
||||
expect(flag).toBe(PatchFlags.DYNAMIC_SLOTS)
|
||||
if (expectedPatchFlag) {
|
||||
expect(flag).toBe(expectedPatchFlag)
|
||||
} else {
|
||||
expect(flag).toBeUndefined()
|
||||
}
|
||||
|
@ -502,14 +505,13 @@ describe('compiler: transform component slots', () => {
|
|||
`<div v-for="i in list">
|
||||
<Comp v-slot="bar">foo</Comp>
|
||||
</div>`,
|
||||
false,
|
||||
)
|
||||
|
||||
assertDynamicSlots(
|
||||
`<div v-for="i in list">
|
||||
<Comp v-slot="bar">{{ i }}</Comp>
|
||||
</div>`,
|
||||
true,
|
||||
PatchFlags.DYNAMIC_SLOTS,
|
||||
)
|
||||
|
||||
// reference the component's own slot variable should not force dynamic slots
|
||||
|
@ -517,14 +519,13 @@ describe('compiler: transform component slots', () => {
|
|||
`<Comp v-slot="foo">
|
||||
<Comp v-slot="bar">{{ bar }}</Comp>
|
||||
</Comp>`,
|
||||
false,
|
||||
)
|
||||
|
||||
assertDynamicSlots(
|
||||
`<Comp v-slot="foo">
|
||||
<Comp v-slot="bar">{{ foo }}</Comp>
|
||||
</Comp>`,
|
||||
true,
|
||||
PatchFlags.DYNAMIC_SLOTS,
|
||||
)
|
||||
|
||||
// #2564
|
||||
|
@ -532,14 +533,35 @@ describe('compiler: transform component slots', () => {
|
|||
`<div v-for="i in list">
|
||||
<Comp v-slot="bar"><button @click="fn(i)" /></Comp>
|
||||
</div>`,
|
||||
true,
|
||||
PatchFlags.DYNAMIC_SLOTS,
|
||||
)
|
||||
|
||||
assertDynamicSlots(
|
||||
`<div v-for="i in list">
|
||||
<Comp v-slot="bar"><button @click="fn()" /></Comp>
|
||||
</div>`,
|
||||
false,
|
||||
)
|
||||
|
||||
// #9380
|
||||
assertDynamicSlots(
|
||||
`<div v-for="i in list">
|
||||
<Comp :i="i">foo</Comp>
|
||||
</div>`,
|
||||
PatchFlags.PROPS,
|
||||
)
|
||||
|
||||
assertDynamicSlots(
|
||||
`<div v-for="i in list">
|
||||
<Comp v-slot="{ value = i }"><button @click="fn()" /></Comp>
|
||||
</div>`,
|
||||
PatchFlags.DYNAMIC_SLOTS,
|
||||
)
|
||||
|
||||
assertDynamicSlots(
|
||||
`<div v-for="i in list">
|
||||
<Comp v-slot:[i]><button @click="fn()" /></Comp>
|
||||
</div>`,
|
||||
PatchFlags.DYNAMIC_SLOTS,
|
||||
)
|
||||
})
|
||||
|
||||
|
|
|
@ -131,9 +131,17 @@ export function buildSlots(
|
|||
// since it likely uses a scope variable.
|
||||
let hasDynamicSlots = context.scopes.vSlot > 0 || context.scopes.vFor > 0
|
||||
// with `prefixIdentifiers: true`, this can be further optimized to make
|
||||
// it dynamic only when the slot actually uses the scope variables.
|
||||
// it dynamic when
|
||||
// 1. the slot arg or exp uses the scope variables.
|
||||
// 2. the slot children use the scope variables.
|
||||
if (!__BROWSER__ && !context.ssr && context.prefixIdentifiers) {
|
||||
hasDynamicSlots = hasScopeRef(node, context.identifiers)
|
||||
hasDynamicSlots =
|
||||
node.props.some(
|
||||
prop =>
|
||||
isVSlot(prop) &&
|
||||
(hasScopeRef(prop.arg, context.identifiers) ||
|
||||
hasScopeRef(prop.exp, context.identifiers)),
|
||||
) || children.some(child => hasScopeRef(child, context.identifiers))
|
||||
}
|
||||
|
||||
// 1. Check for slot with slotProps on component itself.
|
||||
|
|
Loading…
Reference in New Issue