Jak wymusić ponowne renderowanie komponentu w Angular 2?

Jak wymusić ponowne renderowanie komponentu w Angular 2? Dla celów debugowania praca z Reduxem chciałbym wymusić na komponencie ponowne wyrenderowanie widoku, czy to możliwe?

Author: Veve, 2016-01-30

6 answers

Renderowanie następuje po wykryciu zmian. Aby wymusić wykrywanie zmian, tak aby wartości właściwości komponentów, które uległy zmianie, były propagowane do DOM (a następnie przeglądarka wyrenderuje te zmiany w widoku), oto kilka opcji:

  • ApplicationRef.tick () - podobne do Angular 1 ' s $rootScope.$digest() -- tzn. sprawdź pełne drzewo komponentów
  • NgZone.Uruchom (callback) - podobne do $rootScope.$apply(callback) -- tzn. Oceń funkcję callback wewnątrz strefy kątowej 2. I pomyśl, ale nie jestem pewien, że kończy się to sprawdzeniem pełnego drzewa komponentów po wykonaniu funkcji callback.
  • ChangeDetectorRef.detectChanges () - podobne do $scope.$digest() -- tzn. sprawdza tylko ten komponent i jego dzieci

Będziesz musiał zaimportować, a następnie wstrzyknąć ApplicationRef, NgZone, lub ChangeDetectorRef do twojego komponentu.

Dla konkretnego scenariusza, polecam ostatnią opcję, jeśli tylko jeden komponent się zmienił.

 229
Author: Mark Rajcok,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-17 19:06:08

Tx, znalazłem obejście, którego potrzebowałem:

  constructor(private zone:NgZone) {
    // enable to for time travel
    this.appStore.subscribe((state) => {
        this.zone.run(() => {
            console.log('enabled time travel');
        });
    });
Strefa biegania.run wymusi ponowne renderowanie komponentu
 49
Author: born2net,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-30 18:42:29

ChangeDetectorRef approach

import { Component, OnInit, ChangeDetectorRef } from '@angular/core';

export class MyComponent {

    constructor(private cdr: ChangeDetectorRef) { }

    selected(item: any) {
        if (item == 'Department')
            this.isDepartment = true;
        else
            this.isDepartment = false;
        this.cdr.detectChanges();
    }

}
 34
Author: Feng Zhang,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-12-24 15:44:41

Wymuszam przeładowanie komponentu za pomocą *ngIf.

Wszystkie komponenty w moim kontenerze wracają do haków pełnego cyklu życia .

W szablonie:

<ng-container *ngIf="_reload">
    components here 
</ng-container>

Następnie w pliku ts:

public _reload = true;

private reload() {
    setTimeout(() => this._reload = false);
    setTimeout(() => this._reload = true);
}
 23
Author: loonis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-06-11 09:48:34

Inne odpowiedzi tutaj dostarczają rozwiązań dla wyzwalania cykli wykrywania zmian, które zaktualizują widok komponentu (co nie jest takie samo jak pełne ponowne renderowanie).

Pełne ponowne renderowanie, które zniszczyłoby i ponownie uruchomiłoby komponent (wywołanie wszystkich hooków cyklu życia i przebudowanie widoku) może być wykonane za pomocą ng-template, ng-container i ViewContainerRef w następujący sposób:

<div>
  <ng-container #outlet >
  </ng-container>
</div>

<ng-template #content>
  <child></child>
</ng-template>

Następnie w komponencie mającym odniesienie zarówno do #outlet, jak i #content możemy wyczyścić zawartość i wstawić kolejną instancję potomka Składnik:

@ViewChild("outlet", {read: ViewContainerRef}) outletRef: ViewContainerRef;
@ViewChild("content", {read: TemplateRef}) contentRef: TemplateRef<any>;

private rerender() {
    this.outletRef.clear();
    this.outletRef.createEmbeddedView(this.contentRef);
}

Dodatkowo zawartość początkową należy wstawić na AfterContentInit haku:

ngAfterContentInit() {
    this.outletRef.createEmbeddedView(this.contentRef);
}

Pełne rozwiązanie robocze można znaleźć tutaj https://stackblitz.com/edit/angular-component-rerender .

 11
Author: Pavel Gurecki,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-11-08 16:59:57

ChangeDetectorRef.detectChanges() zwykle jest to najbardziej skoncentrowany sposób na zrobienie tego. ApplicationRef.tick() jest zwykle zbyt dużo podejścia do młota kowalskiego.

Aby użyć ChangeDetectorRef.detectChanges(), potrzebujesz tego na górze komponentu:

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

... wtedy zazwyczaj po wstrzyknięciu go do konstruktora wykonujesz tak:

constructor( private cdr: ChangeDetectorRef ) { ... }

Następnie, w odpowiednie miejsce, nazywacie to tak:

this.cdr.detectChanges();

gdzie zadzwonisz ChangeDetectorRef.detectChanges() może być bardzo istotne. Musisz całkowicie zrozum cykl życia i dokładnie jak Twoja aplikacja działa i renderuje swoje komponenty. Nie ma tu substytutu dla pełnego odrabiania lekcji i upewniania się, że rozumiesz kanciasty cykl życia na wylot. Następnie, gdy to zrozumiesz, możesz użyć ChangeDetectorRef.detectChanges() odpowiednio (czasami bardzo łatwo jest zrozumieć, gdzie powinieneś go użyć, innym razem może to być bardzo złożone).

 1
Author: Chris Halcrow,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-08-29 02:32:31