Как заставить рендеринг компонента в Angular 2? В целях отладки, работая с Redux, я хотел бы заставить компонент перерисовать его представление, это возможно?
Как заставить рендеринг компонента в Angular 2? В целях отладки, работая с Redux, я хотел бы заставить компонент перерисовать его представление, это возможно?
Ответы:
Рендеринг происходит после обнаружения изменений. Для принудительного обнаружения изменений, чтобы значения свойств компонентов, которые изменились, были переданы в DOM (а затем браузер отобразит эти изменения в представлении), вот несколько вариантов:
$rootScope.$digest()
т. Е. Проверить полное дерево компонентов$rootScope.$apply(callback)
- т.е. оценивает функцию обратного вызова внутри зоны Angular 2. Я думаю, но я не уверен, что это заканчивается проверкой полного дерева компонентов после выполнения функции обратного вызова.$scope.$digest()
- т.е. проверять только этот компонент и его дочерние элементыВам нужно будет импортировать , а затем инъекционные ApplicationRef
, NgZone
или ChangeDetectorRef
в компонент.
Для вашего конкретного сценария я бы порекомендовал последний вариант, если изменился только один компонент.
this is the first time I am facing an update not working in ng2
. Стратегия обнаружения изменений по умолчанию, поэтому я знаю, что не ошибся со стратегией обнаружения изменений.
this
контекста в обратном вызове POST.
pure:false
в канале. Это работает, но это слишком дорого (неэффективно) для моего варианта использования.
TX, нашел обходной путь, который мне был нужен:
constructor(private zone:NgZone) {
// enable to for time travel
this.appStore.subscribe((state) => {
this.zone.run(() => {
console.log('enabled time travel');
});
});
запуск zone.run заставит компонент повторно выполнить рендеринг
Подход ChangeDetectorRef
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();
}
}
Я принудительно перезагружаю свой компонент, используя * ngIf.
Все компоненты внутри моего контейнера возвращаются к крюкам полного жизненного цикла.
В шаблоне:
<ng-container *ngIf="_reload">
components here
</ng-container>
Тогда в файле ts:
public _reload = true;
private reload() {
setTimeout(() => this._reload = false);
setTimeout(() => this._reload = true);
}
setTimeout()
. Теперь моя работает с простым и легким решением!
Другие ответы здесь предоставляют решения для запуска циклов обнаружения изменений, которые обновят представление компонента (что отличается от полного повторного рендеринга).
Полное повторное рендер, который уничтожит и переинициализировать компонент (вызов все крюки жизненный цикл и восстановление зрения) может быть сделано с помощью ng-template
, ng-container
и ViewContainerRef
в следующим образом:
<div>
<ng-container #outlet >
</ng-container>
</div>
<ng-template #content>
<child></child>
</ng-template>
Затем в компоненте , имеющая ссылку как #outlet
и #content
мы можем очистить содержание торговых точек и вставить другой экземпляр дочернего компонента:
@ViewChild("outlet", {read: ViewContainerRef}) outletRef: ViewContainerRef;
@ViewChild("content", {read: TemplateRef}) contentRef: TemplateRef<any>;
private rerender() {
this.outletRef.clear();
this.outletRef.createEmbeddedView(this.contentRef);
}
Дополнительно начальный контент должен быть вставлен на AfterContentInit
крючок:
ngAfterContentInit() {
this.outletRef.createEmbeddedView(this.contentRef);
}
Полное рабочее решение можно найти здесь https://stackblitz.com/edit/angular-component-rerender .
ChangeDetectorRef.detectChanges()
обычно это самый сфокусированный способ сделать это. ApplicationRef.tick()
обычно слишком много подхода кувалды.
Чтобы использовать ChangeDetectorRef.detectChanges()
, вам нужно это в верхней части вашего компонента:
import { ChangeDetectorRef } from '@angular/core';
... тогда обычно вы называете это псевдонимом, когда вставляете его в свой конструктор так:
constructor( private cdr: ChangeDetectorRef ) { ... }
Затем в соответствующем месте вы называете это так:
this.cdr.detectChanges();
Где вы звоните, ChangeDetectorRef.detectChanges()
может быть очень важным. Вам необходимо полностью понять жизненный цикл и то, как именно ваше приложение функционирует и отображает его компоненты. Здесь нет альтернативы тому, чтобы полностью выполнить домашнюю работу и убедиться, что вы понимаете жизненный цикл Angular наизнанку. Затем, как только вы поймете это, вы сможете использовать его ChangeDetectorRef.detectChanges()
соответствующим образом (иногда очень легко понять, где вы должны его использовать, в других случаях это может быть очень сложным).