feat(compiler): force dynamicSlots flag when inside v-for or v-slot
This commit is contained in:
@@ -49,10 +49,10 @@ export function baseCompile(
|
||||
? [
|
||||
// order is important
|
||||
trackVForSlotScopes,
|
||||
transformExpression,
|
||||
trackSlotScopes
|
||||
transformExpression
|
||||
]
|
||||
: []),
|
||||
trackSlotScopes,
|
||||
optimizeText,
|
||||
transformStyle,
|
||||
transformSlotOutlet,
|
||||
|
||||
@@ -59,6 +59,12 @@ export interface TransformContext extends Required<TransformOptions> {
|
||||
statements: Set<string>
|
||||
hoists: JSChildNode[]
|
||||
identifiers: { [name: string]: number | undefined }
|
||||
scopes: {
|
||||
vFor: number
|
||||
vSlot: number
|
||||
vPre: number
|
||||
vOnce: number
|
||||
}
|
||||
parent: ParentNode | null
|
||||
childIndex: number
|
||||
currentNode: RootNode | TemplateChildNode | null
|
||||
@@ -86,6 +92,12 @@ function createTransformContext(
|
||||
statements: new Set(),
|
||||
hoists: [],
|
||||
identifiers: {},
|
||||
scopes: {
|
||||
vFor: 0,
|
||||
vSlot: 0,
|
||||
vPre: 0,
|
||||
vOnce: 0
|
||||
},
|
||||
prefixIdentifiers,
|
||||
nodeTransforms,
|
||||
directiveTransforms,
|
||||
|
||||
@@ -46,7 +46,7 @@ export const transformFor = createStructuralDirectiveTransform(
|
||||
)
|
||||
|
||||
if (parseResult) {
|
||||
const { helper, addIdentifiers, removeIdentifiers } = context
|
||||
const { helper, addIdentifiers, removeIdentifiers, scopes } = context
|
||||
const { source, value, key, index } = parseResult
|
||||
|
||||
// create the loop render function expression now, and add the
|
||||
@@ -79,6 +79,8 @@ export const transformFor = createStructuralDirectiveTransform(
|
||||
codegenNode
|
||||
})
|
||||
|
||||
// bookkeeping
|
||||
scopes.vFor++
|
||||
if (!__BROWSER__ && context.prefixIdentifiers) {
|
||||
// scope management
|
||||
// inject identifiers to context
|
||||
@@ -88,6 +90,7 @@ export const transformFor = createStructuralDirectiveTransform(
|
||||
}
|
||||
|
||||
return () => {
|
||||
scopes.vFor--
|
||||
if (!__BROWSER__ && context.prefixIdentifiers) {
|
||||
value && removeIdentifiers(value)
|
||||
key && removeIdentifiers(key)
|
||||
|
||||
@@ -32,22 +32,33 @@ const isStaticExp = (p: JSChildNode): p is SimpleExpressionNode =>
|
||||
|
||||
const defaultFallback = createSimpleExpression(`undefined`, false)
|
||||
|
||||
// A NodeTransform that tracks scope identifiers for scoped slots so that they
|
||||
// don't get prefixed by transformExpression. This transform is only applied
|
||||
// in non-browser builds with { prefixIdentifiers: true }
|
||||
// A NodeTransform that:
|
||||
// 1. Tracks scope identifiers for scoped slots so that they don't get prefixed
|
||||
// by transformExpression. This is only applied in non-browser builds with
|
||||
// { prefixIdentifiers: true }.
|
||||
// 2. Track v-slot depths so that we know a slot is inside another slot.
|
||||
// Note the exit callback is executed before buildSlots() on the same node,
|
||||
// so only nested slots see positive numbers.
|
||||
export const trackSlotScopes: NodeTransform = (node, context) => {
|
||||
if (
|
||||
node.type === NodeTypes.ELEMENT &&
|
||||
(node.tagType === ElementTypes.COMPONENT ||
|
||||
node.tagType === ElementTypes.TEMPLATE)
|
||||
) {
|
||||
// We are only checking non-empty v-slot here
|
||||
// since we only care about slots that introduce scope variables.
|
||||
const vSlot = findDir(node, 'slot')
|
||||
if (vSlot) {
|
||||
const { addIdentifiers, removeIdentifiers } = context
|
||||
const slotProps = vSlot.exp
|
||||
slotProps && addIdentifiers(slotProps)
|
||||
if (!__BROWSER__ && context.prefixIdentifiers) {
|
||||
slotProps && context.addIdentifiers(slotProps)
|
||||
}
|
||||
context.scopes.vSlot++
|
||||
return () => {
|
||||
slotProps && removeIdentifiers(slotProps)
|
||||
if (!__BROWSER__ && context.prefixIdentifiers) {
|
||||
slotProps && context.removeIdentifiers(slotProps)
|
||||
}
|
||||
context.scopes.vSlot--
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -94,7 +105,12 @@ export function buildSlots(
|
||||
const { children, loc } = node
|
||||
const slotsProperties: Property[] = []
|
||||
const dynamicSlots: (ConditionalExpression | CallExpression)[] = []
|
||||
let hasDynamicSlots = false
|
||||
|
||||
// If the slot is inside a v-for or another v-slot, force it to be dynamic
|
||||
// since it likely uses a scope variable.
|
||||
// TODO: This can be further optimized to only make it dynamic when the slot
|
||||
// actually uses the scope variables.
|
||||
let hasDynamicSlots = context.scopes.vSlot > 0 || context.scopes.vFor > 0
|
||||
|
||||
// 1. Check for default slot with slotProps on component itself.
|
||||
// <Comp v-slot="{ prop }"/>
|
||||
|
||||
Reference in New Issue
Block a user