2016-05-22 8 views
15

In Angular 1 sollten alle DOM-Manipulationen in Direktiven vorgenommen werden, um eine korrekte Testbarkeit sicherzustellen, aber was ist mit Angular 2? Wie hat sich das geändert?Wohin gehört die DOM-Manipulation in Angular 2?

Ich habe nach guten Artikeln gesucht oder nach Informationen darüber, wo man DOM manipulieren kann und wie man dabei denkt, aber ich komme jedes Mal leer.

Nehmen Sie diese Komponente zum Beispiel (das ist wirklich eine Richtlinie aber sie behauptet, dass es nicht):

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; 
    } 
} 

Hat Ereignisbindung zum Beispiel in einem Konstruktor gehört, oder sollte dies in der ngAfterViewInit Funktion gesetzt werden oder irgendwo anders? Sollten Sie versuchen, die DOM-Manipulation einer Komponente in eine Direktive zu überführen?

Es ist alles nur eine Unschärfe im Moment, also bin ich mir nicht sicher, ob ich das richtig mache und ich bin mir sicher, dass ich nicht der Einzige bin.

Welche Regeln gelten für die DOM-Manipulation in Angular2?

Antwort

9

Direkte DOM-Manipulation sollte in Angular2 vollständig vermieden werden.

Benutze stattdessen Bindungen wie:

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

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

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

Können Sie es ausarbeiten? – Chrillewoodz

+0

'@HostListener (...)' registriert einen Event-Listener und '@HostBinding (...)' aktualisiert den 'height' Style-Wert auf den Wert, der' number' zugewiesen ist. Der Ereignishandler war nicht korrekt. Ich habe meine Antwort aktualisiert (tut mir leid, war nur am Telefon, als ich es schrieb). –

+2

Die direkte DOM-Manipulation ist nicht mit dem serverseitigen Rendern und der Verwendung der Angulars WebWorker-Unterstützung kompatibel. –

14

Basierend auf Lösung von Entwicklern empfehlen: 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 
    } 
} 

Achtung: Die Kinder Name mit meine Namen zu beginnen hat und in der Vorlage brauchst du #.

+1

Vergessen Sie nicht, die entsprechenden Importe hinzuzufügen: import {AfterViewInit, ViewChild} von '@ angular/core'; Code-Auszug von: https://angular.io/docs/ts/latest/cookbook/component-communication.html#!# parent-to-view-child –

+0

Sie müssen auch {ElementRef} aus '@ angular/core' importieren; –

+0

Wollen Sie sagen, dass das Präfix * my * im Namen vorhanden sein muss? Oder meinen Sie, dass der Name, auf den wir in '@ViewChild ('whatever') 'verweisen,' 'was auch immer'' im Markup der Vorlage entsprechen muss? –