Frage So lösen Sie manuell ein Änderungsereignis aus - angular2


Angesichts der folgenden Komponenten:

@Component({
    selector: 'compA',
    template:  template: `<compB [item]=item></compB>`
})
export class CompA {
    item:any;
    updateItem():void {
        item[name] = "updated name";
    }
}

@Component({
    selector: 'compB',
    template:  template: `<p>{{item[name]}}</p>`
})
export class CompB implements OnInit{
    @Input() item: any;
    someArray: any[];

    ngOnInit():void {
        someArray.push("something");
    }
}

Soweit ich das verstanden habe, es sei denn die komplette item Objekt wird geändert, angular2 erkennt die Änderungen nicht item. Daher möchte ich ein Änderungsereignis manuell für item wenn das updateItem Methode wird aufgerufen. Und danach, mach die Kindkomponente, d.h. CompB neu gerendert, als ob eckig eine Änderung auf dem regulären Weg erkannt hätte.

Derzeit habe ich die Implementierung des ngOnInit Methode von für CompB und nenne diese Methode im Inneren updateItem Methode durch a ViewChild Verknüpfung. Ein anderer Teil der Geschichte ist, dass meine eigentliche Quelle Objekte wie someArray die ich gerne in jedem Render zurücksetzen würde. Ich bin mir nicht sicher, ob das erneute Rendern zurückgesetzt wird someArray obwohl. Momentan setze ich sie in der ngOnInit Methode.

Also, meine Frage ist: Wie trigger ich Re-Rendering für Änderungen an tieferen Elementen eines Elternobjekts?

Vielen Dank


8
2017-07-06 06:48


Ursprung


Antworten:


Soweit ich das verstanden habe, es sei denn das komplette Item Objekt ist   geändert, angular2 erkennt die Änderungen am Artikel nicht.

Es ist nicht so einfach. Sie müssen zwischen Auslösen unterscheiden ngOnChanges wenn Objekt mutiert ist und DOM-Update der untergeordneten Komponente. Angular erkennt das nicht item wird geändert und löst kein a aus ngOnChanges Lifecycle-Hook, aber das DOM wird immer noch aktualisiert, wenn Sie auf eine bestimmte Eigenschaft des item in der Vorlage. Dies liegt daran, dass der Verweis auf das Objekt beibehalten wird. Deshalb, um dieses Verhalten zu haben:

Und danach, mache die untergeordnete Komponente, d. H. CompB, neu gerendert als ob   eckig erkannte eine Veränderung des normalen Weges.

Sie müssen nichts speziell tun, da Sie im DOM immer noch ein Update haben.

Manuelle Änderungserkennung

Sie können einen Änderungsmelder einfügen und so auslösen:

@Component({
    selector: 'compA',
    template:  template: `<compB [item]=item></compB>`
})
export class CompA {
    item:any;
    constructor(cd: ChangeDetectorRef) {}

    updateItem():void {
        item[name] = "updated name";
        this.cd.detectChanges();
    }
}

Dies löst die Änderungserkennung für die aktuelle Komponente und alle untergeordneten Elemente aus.

Aber es wird in Ihrem Fall keine Wirkung haben Denn obwohl Angular keine Änderung in item es läuft noch Änderungserkennung für das Kind B Komponente und aktualisiert das DOM.

Es sei denn Sie nutzen ChangeDetectionStrategy.OnPush. In diesem Fall wäre ein Weg für Sie eine manuelle Überprüfung in der ngDoCheck Haken des CompB:

import { ChangeDetectorRef } from '@angular/core';

export class CompB implements OnInit{
    @Input() item: any;
    someArray: any[];
    previous;

    constructor(cd: ChangeDetectorRef) {}

    ngOnInit():void {
        this.previous = this.item.name;
        someArray.push("something");
    }

    ngDoCheck() {
      if (this.previous !== this.item.name) {
        this.cd.detectChanges();
      }
    }
}

Weitere Informationen finden Sie in den folgenden Artikeln:


6
2017-07-06 06:52