@@ -4,6 +4,7 @@ import { genHandlers } from './events'
4
4
import baseDirectives from '../directives/index'
5
5
import { camelize , no , extend } from 'shared/util'
6
6
import { baseWarn , pluckModuleFunction } from '../helpers'
7
+ import { emptySlotScopeToken } from '../parser/index'
7
8
8
9
type TransformFunction = ( el : ASTElement , code : string ) => string ;
9
10
type DataGenFunction = ( el : ASTElement ) => string ;
@@ -268,7 +269,7 @@ export function genData (el: ASTElement, state: CodegenState): string {
268
269
}
269
270
// scoped slots
270
271
if ( el . scopedSlots ) {
271
- data += `${ genScopedSlots ( el . scopedSlots , state ) } ,`
272
+ data += `${ genScopedSlots ( el , el . scopedSlots , state ) } ,`
272
273
}
273
274
// component v-model
274
275
if ( el . model ) {
@@ -357,18 +358,36 @@ function genInlineTemplate (el: ASTElement, state: CodegenState): ?string {
357
358
}
358
359
359
360
function genScopedSlots (
361
+ el : ASTElement ,
360
362
slots : { [ key : string ] : ASTElement } ,
361
363
state : CodegenState
362
364
) : string {
363
- const hasDynamicKeys = Object . keys ( slots ) . some ( key => {
365
+ // by default scoped slots are considered "stable", this allows child
366
+ // components with only scoped slots to skip forced updates from parent.
367
+ // but in some cases we have to bail-out of this optimization
368
+ // for example if the slot contains dynamic names, has v-if or v-for on them...
369
+ let needsForceUpdate = Object . keys ( slots ) . some ( key => {
364
370
const slot = slots [ key ]
365
371
return slot . slotTargetDynamic || slot . if || slot . for
366
372
} )
373
+ // OR when it is inside another scoped slot (the reactivity is disconnected)
374
+ // #9438
375
+ if ( ! needsForceUpdate ) {
376
+ let parent = el . parent
377
+ while ( parent ) {
378
+ if ( parent . slotScope && parent . slotScope !== emptySlotScopeToken ) {
379
+ needsForceUpdate = true
380
+ break
381
+ }
382
+ parent = parent . parent
383
+ }
384
+ }
385
+
367
386
return `scopedSlots:_u([${
368
387
Object . keys ( slots ) . map ( key => {
369
388
return genScopedSlot ( slots [ key ] , state )
370
389
} ) . join ( ',' )
371
- } ]${ hasDynamicKeys ? `,true` : `` } )`
390
+ } ]${ needsForceUpdate ? `,true` : `` } )`
372
391
}
373
392
374
393
function genScopedSlot (
@@ -382,7 +401,10 @@ function genScopedSlot (
382
401
if ( el . for && ! el . forProcessed ) {
383
402
return genFor ( el , state , genScopedSlot )
384
403
}
385
- const fn = `function(${ String ( el . slotScope ) } ){` +
404
+ const slotScope = el . slotScope === emptySlotScopeToken
405
+ ? ``
406
+ : String ( el . slotScope )
407
+ const fn = `function(${ slotScope } ){` +
386
408
`return ${ el . tag === 'template'
387
409
? el . if && isLegacySyntax
388
410
? `(${ el . if } )?${ genChildren ( el , state ) || 'undefined' } :undefined`
0 commit comments