Rispondi alle modifiche DOM in Angular utilizzando l'API Web MutationObserver
Tempo di lettura: 4 minuti

Nel Rispondi alle modifiche DOM con gli osservatori di mutazione articolo, abbiamo appreso Osservatori di mutazioni DOM, che ha sostituito il goffo Eventi di mutazione DOM. Sia gli eventi di mutazione che gli osservatori di mutazione sono stati progettati per informare lo script delle modifiche alla struttura del DOM. Questi includono:

  • l’aggiunta o la rimozione di elementi
  • modifiche agli attributi di un elemento
  • modifiche ai dati del personaggio (ovvero, modifiche a un nodo di testo)

Osservando l’elenco sopra, diventa subito evidente che Mutation Observers può anche aiutare gli sviluppatori Angular a rispondere a eventi DOM che altrimenti rimarrebbero sfuggenti. In questo tutorial, vedremo quanto è facile sfruttare la potenza del Osservatore di mutazioni API Web per ricevere aggiornamenti ogni volta che gli elementi figlio di un componente cambiano.

Presentazione dell’app Console di gestione del catalogo dei single

Ecco un’app Angular per gestire la copertina di un catalogo di singoli di musica digitale:

È un’app molto semplice che ci consente di aggiungere e rimuovere elementi da un elenco non ordinato. Non sorprende che non sia necessario molto markup HTML per farlo funzionare:

<h1>Singles Catalog</h1>
<ul>
  <li *ngFor="let artwork of singlesArtwork">
  <img [src]="artwork" /><button (click)="removeArtwork(artwork)">Remove</button>
  </li>
</ul>
<button *ngIf="showAddButton; else showMessage" (click)="addArtwork()">Add Next Single</button>

<ng-template #showMessage>No more singles to add.</ng-template>


Leggi:
Dichiara e rispondi a un evento Dom Element Ready

Creazione di un AppService in Angular

Le immagini sono fornite da un servizio tramite il pubblico fetchSinglesArtwork() metodo. Rimuove gli elementi dall’inizio dell’elenco e li emette come RxJS Observable. Un ritardo di 500 millisecondi viene aggiunto per emulare una chiamata di rete che verrebbe utilizzata per recuperare gli URL delle immagini da un archivio dati esterno. Ha anche un metodo per rimuovere le immagini che sostituisce gli elementi precedentemente rimossi:

import { Injectable } from '@angular/core';
import * as Rx from 'rxjs/Rx';

const ROOT = 'https://i1.sndcdn.com/artworks-';

@Injectable()
export class AppService {
  private singlesArtwork = [
    ROOT + 'nOmzKy8phBjdHggR-B4aC8Q-t200x200.jpg', 
    ROOT + 'b5jyk6LpdxWVWWz5-jGpxXw-t200x200.jpg', 
    ROOT + 'OCRwxXbSBQwex4mM-LY2qWg-t200x200.jpg',
    ROOT + '2n1JKCcFA6Gg6UH7-GsP3HA-t200x200.jpg',
    ROOT + 'NXjocVbpYjLOCwSx-9VELtA-t200x200.jpg'
  ];

  public fetchSinglesArtwork(howMany: number = 1): Rx.Observable<string[]> {
    return Rx.Observable
      .of(this.singlesArtwork.splice(0, howMany))
      .delay(500);
  }

  public removeSinglesArtwork(artwork: string): void {
    this.singlesArtwork.push(artwork);
  }
}

Recupero dell’elenco iniziale

All’avvio, la nostra app mostra le prime tre immagini. Per prenderli, il AppComponent inietta il nostro servizio nel costruttore e lo invoca fetchSinglesArtwork() metodo. Nella funzione di richiamata dell’abbonamento, gli URL delle singole opere d’arte sono archiviati nel pubblico singleArtwork variabile a cui si fa riferimento dal modello. È un Set piuttosto che un normale array in modo da poter garantire che l’elenco non contenga mai duplicati. Naturalmente, se il servizio è codificato correttamente, ciò non dovrebbe mai accadere.

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  private singlesArtwork: Set<string>;
  public showAddButton = true;

  constructor(private appService: AppService) { 
    appService.fetchSinglesArtwork(3)
      .subscribe(singlesArtwork => this.singlesArtwork = new Set<string>(singlesArtwork));
  }
  // more code...
}

Leggi: RXJS Observables Primer in angolare

Aggiunta di un elemento all’elenco

Facendo clic su Aggiungi prossimo singolo il pulsante richiama il addArtwork() metodo, che a sua volta chiama fetchSinglesArtwork(). Nel addArtwork() funzione di callback dell’abbonamento, l’artwork viene aggiunto fintanto che sono rimasti elementi nell’array; in caso contrario, il Aggiungere il pulsante è sostituito da un messaggio che indica che non ci sono più singoli da aggiungere:

public addArtwork(): void {
  this.appService
    .fetchSinglesArtwork()
    .subscribe(singlesArtwork => {
      if (singlesArtwork.length > 0) {
        this.singlesArtwork = this.singlesArtwork.add(singlesArtwork[0]);
      } else {
        this.showAddButton = false;
      }
    });
}

Rimozione di un elemento dall’elenco

Accanto a ogni immagine, c’è un pulsante per rimuoverla dall’elenco che richiama il metodo removeArtwork(). A sua volta, chiama il metodo removeSinglesArtwork() del servizio, passando l’URL dell’immagine in modo che i dati mancanti possano essere sostituiti nel singleArtwork Vettore:

public removeArtwork(artwork: string): void {
  this.singlesArtwork.delete(artwork);
  this.appService.removeSinglesArtwork(artwork);
  this.showAddButton = true;
}

La Direttiva DomChange in Angular

Nelle applicazioni angolari, il Osservatore di mutazioni L’API è probabilmente implementata al meglio come direttiva. Il ElementoRif viene inserito come parametro del costruttore in modo che possiamo accedere direttamente all’elemento del nodo. Quindi ogni modifica DOM emette un evento personalizzato che passa la modifica stessa come argomento:

import { Directive, ElementRef, EventEmitter, OnDestroy, Output } from '@angular/core';

@Directive({
  selector: '[domChange]'
})
export class DomChangeDirective implements OnDestroy {
  private changes: MutationObserver;

  @Output()
  public domChange = new EventEmitter();

  constructor(private elementRef: ElementRef) {
    const element = this.elementRef.nativeElement;

    this.changes = new MutationObserver((mutations: MutationRecord[]) => {
        mutations.forEach((mutation: MutationRecord) => this.domChange.emit(mutation));
      }
    );

    this.changes.observe(element, {
      attributes: true,
      childList: true,
      characterData: true
    });
  }

  ngOnDestroy(): void {
    this.changes.disconnect();
  }
}

Possiamo ora vincolare la direttiva al onDomChange() gestore nel modello come segue:

<ul (domChange)="onDomChange($event)">

In questo caso, il $ evento sarà un ElementoRif al

    elemento.

    In AppComponent onDomChange() gestore, possiamo rispondere alle modifiche DOM in qualsiasi modo desideriamo. A scopo dimostrativo, cercheremo solo l’aggiunta e la rimozione di

  • elementi e invia il primo alla console:

    public onDomChange(mutationRecord: MutationRecord): void {
      const addedNodes   = mutationRecord.addedNodes;
      const removedNodes = mutationRecord.removedNodes;
    
      if (  addedNodes.length > 0
        && (addedNodes.item(0) as HTMLElement).tagName === 'LI') {
        console.log('Added nodes: ', addedNodes.item(0));
      } else if (removedNodes.length > 0
             && (removedNodes.item(0) as HTMLElement).tagName === 'LI') {
        console.log('Removed nodes: ', removedNodes.item(0));
      }
    }
    

    Si noti che entrambi i nodi aggiunti e nodi rimossi gli elementi sono Nodo oggetti in TypeScript, quindi dobbiamo lanciarli come an Elemento HTML per accedere ai suoi attributi e metodi. Possiamo vedere alcuni esempi di output qui:

    Tutorial Dom e Angular

    Troverai l’applicazione Catalogo Singles su stackblitz.

    Conclusione

    Grazie al Osservatore di mutazioni API Web, possiamo fare cose nelle nostre app Angular che altrimenti sarebbero molto difficili. Fai solo attenzione a rispettare la gerarchia dei componenti ed evita di ascoltare i cambiamenti all’interno di altri componenti. Ad esempio, se devi rispondere alle modifiche DOM all’interno di un componente figlio, aggiungi la direttiva al suo modello e quindi passa i dati necessari al genitore tramite un Emettitore di eventi.

    Leggi: Graziosa gestione degli errori RxJS

Source link

Di Simone Serra

Web Designer Freelancer Realizzazione Siti Web Serra Simone Realizzo siti web, portali ed e-commerce con focus specifici sull’usabilità, l’impatto grafico, una facile gestione e soprattutto in grado di produrre conversioni visitatore-cliente. Elaboro siti internet, seguendo gli standard Web garantendo la massima compatibilità con tutti i devices. Sviluppo e-commerce personalizzati, multilingua, geolocalizzati per potervi mettere nelle migliori condizioni di vendita. Posiziono il tuo sito su Google per dare maggiore visibilità alla tua attività sui motori di ricerca con SEO di base o avanzato.