@@ -52,13 +52,19 @@ export function initSlots(
52
52
53
53
instance . slots = shallowReactive ( { } )
54
54
const renderedSlotKeys : Set < string > [ ] = [ ]
55
+ /**
56
+ * Maintain a queue for each slot name, so that we can
57
+ * render the next slot when the highest level slot was removed
58
+ */
55
59
const slotsQueue : Record < string , [ level : number , slot : Slot ] [ ] > = { }
56
60
rawSlots . forEach ( ( slots , index ) => {
57
61
const isDynamicSlot = isDynamicSlotFn ( slots )
58
62
if ( isDynamicSlot ) {
59
63
firstEffect ( instance , ( ) => {
60
64
const renderedKeys = ( renderedSlotKeys [ index ] ||= new Set ( ) )
61
65
let dynamicSlot = slots ( )
66
+ // cleanup slots and re-calc to avoid diffing slots between renders
67
+ // cleanup will return a slotNames array contains the slot names that need to be restored
62
68
const restoreSlotNames = cleanupSlot ( index )
63
69
if ( isArray ( dynamicSlot ) ) {
64
70
for ( const slot of dynamicSlot ) {
@@ -67,6 +73,7 @@ export function initSlots(
67
73
} else if ( dynamicSlot ) {
68
74
registerSlot ( dynamicSlot . name , dynamicSlot . fn , index , renderedKeys )
69
75
}
76
+ // restore after re-calc slots
70
77
if ( restoreSlotNames . length ) {
71
78
for ( const key of restoreSlotNames ) {
72
79
const [ restoreLevel , restoreFn ] = slotsQueue [ key ] [ 0 ]
@@ -75,6 +82,7 @@ export function initSlots(
75
82
addSlot ( key , restoreFn )
76
83
}
77
84
}
85
+ // delete stale slots
78
86
for ( const name of renderedKeys ) {
79
87
if (
80
88
! ( isArray ( dynamicSlot )
@@ -95,14 +103,16 @@ export function initSlots(
95
103
96
104
function cleanupSlot ( level : number ) {
97
105
const restoreSlotNames : string [ ] = [ ]
106
+ // remove slots from all queues
98
107
Object . keys ( slotsQueue ) . forEach ( slotName => {
99
108
const index = slotsQueue [ slotName ] . findIndex ( ( [ l ] ) => l === level )
100
109
if ( index > - 1 ) {
101
- slotsQueue [ slotName ] . splice ( index , 1 )
110
+ slotsQueue [ slotName ] = slotsQueue [ slotName ] . filter ( ( [ l ] ) => l !== level )
102
111
if ( ! slotsQueue [ slotName ] . length ) {
103
112
delete slotsQueue [ slotName ]
104
113
return
105
114
}
115
+ // restore next slot if the removed slots was the highest level slot
106
116
if ( index === 0 ) {
107
117
renderedSlotKeys [ level ] && renderedSlotKeys [ level ] . delete ( slotName )
108
118
restoreSlotNames . push ( slotName )
@@ -121,13 +131,15 @@ export function initSlots(
121
131
slotsQueue [ name ] ||= [ ]
122
132
slotsQueue [ name ] . push ( [ level , slot ] )
123
133
slotsQueue [ name ] . sort ( ( a , b ) => b [ 0 ] - a [ 0 ] )
134
+ // hide old slot if the registered slot is the highest level
124
135
if ( slotsQueue [ name ] [ 1 ] ) {
125
136
const hidenLevel = slotsQueue [ name ] [ 1 ] [ 0 ]
126
137
renderedSlotKeys [ hidenLevel ] && renderedSlotKeys [ hidenLevel ] . delete ( name )
127
138
}
128
139
if ( slotsQueue [ name ] [ 0 ] [ 0 ] === level ) {
129
140
renderedKeys && renderedKeys . add ( name )
130
141
}
142
+ // render the highest level slot
131
143
addSlot ( name , slotsQueue [ name ] [ 0 ] [ 1 ] )
132
144
}
133
145
0 commit comments