2016-05-22 22 views
15

In Angular 1 tutte le manipolazioni del DOM devono essere eseguite in direttive per garantire un'adeguata testabilità, ma per quanto riguarda Angular 2? Come è cambiato?Dove si trova la manipolazione DOM in Angular 2?

Sono stato alla ricerca di buoni articoli o di qualsiasi informazione su dove mettere la manipolazione DOM e su come pensare quando lo si fa, ma io vengo vuoto ogni volta.

Prendete questa componente, ad esempio (questo è davvero una direttiva, ma facciamo finta che non è):

export class MyComponent { 

    constructor(private _elementRef: ElementRef) { 

    this.setHeight(); 

    window.addEventListener('resize', (e) => { 
     this.setHeight(); 
    }); 
    } 

    setHeight() { 
    this._elementRef.nativeElement.style.height = this.getHeight() + 'px'; 
    } 

    getHeight() { 
    return window.innerHeight; 
    } 
} 

Vuol vincolante evento appartengono in un costruttore per esempio, o questo dovrebbe essere messo in funzione ngAfterViewInit o altrove? Dovresti provare a scomporre la manipolazione del DOM di un componente in una direttiva?

Al momento è tutto solo un offuscamento quindi non sono sicuro di averlo fatto correttamente e sono sicuro di non essere l'unico.

Quali sono le regole per la manipolazione DOM in Angular2?

risposta

9

La manipolazione diretta DOM deve essere evitata interamente in Angular2.

Utilizzare invece binding come:

export class MyComponent { 
    constructor() { 
    this.setHeight(); 
    } 

    @HostBinding('style.height.px') 
    height:number; 

    @HostListener('window:resize', ['$event']) 
    setHeight() { 
    this.height = window.innerHeight; 
    } 
} 
+0

Puoi elaborare? – Chrillewoodz

+0

'@HostListener (...)' registra un listener di eventi e '@HostBinding (...)' aggiorna il valore di stile 'height' sul valore assegnato a' number'. Il gestore dell'evento non era corretto. Ho aggiornato la mia risposta (mi dispiace, era solo al telefono quando l'ho scritto). –

+2

La manipolazione diretta DOM non è compatibile con il rendering lato server e utilizza il supporto di Angers of WebWorkers. –

14

Sulla base di consigliare la soluzione dagli sviluppatori: http://angularjs.blogspot.de/2016/04/5-rookie-mistakes-to-avoid-with-angular.html

@Component({ 
    selector: 'my-comp', 
    template: ` 
    <div #myContainer> 
    </div> 
    ` 
}) 
export class MyComp implements AfterViewInit { 
    @ViewChild('myContainer') container: ElementRef; 

    constructor() {} 

    ngAfterViewInit() { 
    var container = this.container.nativeElement; 
    console.log(container.width); // or whatever 
    } 
} 

Attenzione: Il nome della vista bambino deve cominciare con mia Nome e nella modello di cui hai bisogno #.

+1

Non dimenticare di aggiungere le importazioni appropriate: import {AfterViewInit, ViewChild} da '@ angular/core'; codice estratto da: https://angular.io/docs/ts/latest/cookbook/component-communication.html#!# parent-to-view-child –

+0

Dovrai anche includere import {ElementRef} da '@ angular/core'; –

+0

Stai dicendo che il prefisso * mio * deve essere presente nel nome? O intendevi che il nome a cui ci riferiamo in '@ViewChild ('qualunque cosa')' deve corrispondere a '# qualunque cosa? Nel markup del template? –