@@ -52,13 +52,19 @@ export function initSlots(
5252
5353 instance . slots = shallowReactive ( { } )
5454 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+ */
5559 const slotsQueue : Record < string , [ level : number , slot : Slot ] [ ] > = { }
5660 rawSlots . forEach ( ( slots , index ) => {
5761 const isDynamicSlot = isDynamicSlotFn ( slots )
5862 if ( isDynamicSlot ) {
5963 firstEffect ( instance , ( ) => {
6064 const renderedKeys = ( renderedSlotKeys [ index ] ||= new Set ( ) )
6165 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
6268 const restoreSlotNames = cleanupSlot ( index )
6369 if ( isArray ( dynamicSlot ) ) {
6470 for ( const slot of dynamicSlot ) {
@@ -67,6 +73,7 @@ export function initSlots(
6773 } else if ( dynamicSlot ) {
6874 registerSlot ( dynamicSlot . name , dynamicSlot . fn , index , renderedKeys )
6975 }
76+ // restore after re-calc slots
7077 if ( restoreSlotNames . length ) {
7178 for ( const key of restoreSlotNames ) {
7279 const [ restoreLevel , restoreFn ] = slotsQueue [ key ] [ 0 ]
@@ -75,6 +82,7 @@ export function initSlots(
7582 addSlot ( key , restoreFn )
7683 }
7784 }
85+ // delete stale slots
7886 for ( const name of renderedKeys ) {
7987 if (
8088 ! ( isArray ( dynamicSlot )
@@ -95,14 +103,16 @@ export function initSlots(
95103
96104 function cleanupSlot ( level : number ) {
97105 const restoreSlotNames : string [ ] = [ ]
106+ // remove slots from all queues
98107 Object . keys ( slotsQueue ) . forEach ( slotName => {
99108 const index = slotsQueue [ slotName ] . findIndex ( ( [ l ] ) => l === level )
100109 if ( index > - 1 ) {
101- slotsQueue [ slotName ] . splice ( index , 1 )
110+ slotsQueue [ slotName ] = slotsQueue [ slotName ] . filter ( ( [ l ] ) => l !== level )
102111 if ( ! slotsQueue [ slotName ] . length ) {
103112 delete slotsQueue [ slotName ]
104113 return
105114 }
115+ // restore next slot if the removed slots was the highest level slot
106116 if ( index === 0 ) {
107117 renderedSlotKeys [ level ] && renderedSlotKeys [ level ] . delete ( slotName )
108118 restoreSlotNames . push ( slotName )
@@ -121,13 +131,15 @@ export function initSlots(
121131 slotsQueue [ name ] ||= [ ]
122132 slotsQueue [ name ] . push ( [ level , slot ] )
123133 slotsQueue [ name ] . sort ( ( a , b ) => b [ 0 ] - a [ 0 ] )
134+ // hide old slot if the registered slot is the highest level
124135 if ( slotsQueue [ name ] [ 1 ] ) {
125136 const hidenLevel = slotsQueue [ name ] [ 1 ] [ 0 ]
126137 renderedSlotKeys [ hidenLevel ] && renderedSlotKeys [ hidenLevel ] . delete ( name )
127138 }
128139 if ( slotsQueue [ name ] [ 0 ] [ 0 ] === level ) {
129140 renderedKeys && renderedKeys . add ( name )
130141 }
142+ // render the highest level slot
131143 addSlot ( name , slotsQueue [ name ] [ 0 ] [ 1 ] )
132144 }
133145
0 commit comments