@@ -15,6 +15,7 @@ import {
15
15
} from './managers/index.js' ;
16
16
import { useMutation } from '../services/MutationService.js' ;
17
17
import { noop , isDev , isFunction , isArray } from '../utils/index.js' ;
18
+ import { features } from './features.js' ;
18
19
19
20
let id = 0 ;
20
21
@@ -315,44 +316,65 @@ export class Base<T extends BaseProps = BaseProps> {
315
316
this [ `__${ service . toLowerCase ( ) } ` ] = new this . __managers [ `${ service } Manager` ] ( this ) ;
316
317
}
317
318
318
- const service = useMutation ( document . documentElement , { childList : true , subtree : true } ) ;
319
+ const service = useMutation ( document . querySelector ( 'main' ) , {
320
+ childList : true ,
321
+ subtree : true ,
322
+ attributes : true ,
323
+ attributeFilter : [ features . get ( 'attributes' ) . component ] ,
324
+ } ) ;
319
325
const key = this . constructor . __mutationSymbol ;
320
326
if ( ! service . has ( key ) ) {
321
327
service . add ( key , ( props ) => {
322
- const updates = new Map < Base , ( ) => any > ( ) ;
323
- const terminations = new Map < Base , ( ) => any > ( ) ;
328
+ const actions = new Map < any , ( ) => any > ( ) ;
329
+ const instances = getInstances ( ) ;
324
330
325
331
for ( const mutation of props . mutations ) {
326
- if ( mutation . type !== 'childList' ) continue ;
327
-
328
- // Terminate components whose root element has been removed from the DOM
332
+ // Update parent instance when an instance node has been removed from the DOM.
329
333
for ( const node of mutation . removedNodes ) {
330
- if ( node . isConnected ) continue ;
334
+ if ( node . nodeType !== Node . ELEMENT_NODE ) continue ;
335
+
336
+ for ( const instance of instances ) {
337
+ if ( actions . has ( instance . $parent ?? instance ) ) continue ;
338
+ if ( instance . $el . isConnected ) continue ;
339
+ if ( ! node . contains ( instance . $el ) ) continue ;
340
+
341
+ actions . set ( instance . $parent ?? instance , ( ) => {
342
+ if ( instance . $parent ) {
343
+ instance . $update ( ) ;
344
+ } else {
345
+ instance . $destroy ( ) ;
346
+ }
347
+ } ) ;
348
+ }
349
+ }
350
+
351
+ // Update instances whose child DOM has changed
352
+ for ( const node of mutation . addedNodes ) {
353
+ if ( node . nodeType !== Node . ELEMENT_NODE ) continue ;
354
+ if ( actions . has ( node ) ) continue ;
331
355
332
- for ( const instance of getInstances ( ) ) {
333
- if ( ! terminations . has ( instance ) && ( node === instance . $el || node . contains ( instance . $el ) ) ) {
334
- terminations . set ( instance , ( ) => instance . $terminate ( ) ) ;
356
+ for ( const instance of instances ) {
357
+ if ( instance . $el . contains ( node ) ) {
358
+ actions . set ( node , ( ) => instance . $update ( ) ) ;
335
359
}
336
360
}
337
361
}
338
362
339
- // Update components whose children have been terminationd
340
- for ( const node of mutation . addedNodes ) {
341
- for ( const instance of getInstances ( ) ) {
342
- if ( ! updates . has ( instance ) && instance . $el . contains ( node ) ) {
343
- updates . set ( instance , ( ) => instance . $update ( ) ) ;
363
+ // Update instances when a data-component attribute has changed
364
+ if ( mutation . type === 'attributes' ) {
365
+ for ( const instance of instances ) {
366
+ if ( actions . has ( instance ) ) continue ;
367
+
368
+ if ( instance . $el . contains ( mutation . target ) ) {
369
+ actions . set ( instance , ( ) => instance . $update ( ) ) ;
344
370
}
345
371
}
346
372
}
347
373
}
348
374
349
- for ( const update of updates . values ( ) ) {
375
+ for ( const update of actions . values ( ) ) {
350
376
update ( ) ;
351
377
}
352
-
353
- for ( const termination of terminations . values ( ) ) {
354
- termination ( ) ;
355
- }
356
378
} ) ;
357
379
}
358
380
0 commit comments