Как заставить рендеринг компонента в Angular 2? В целях отладки при работе с Redux я хотел бы заставить компонент перерисовать его, это возможно?
Как принудительно перепрофилировать компонент в Angular 2?
Ответ 1
Рендеринг происходит после обнаружения изменений. Для принудительного обнаружения изменений, чтобы значения свойств компонентов, которые изменились, были переданы в DOM (а затем браузер отобразит эти изменения в представлении), вот несколько вариантов:
- ApplicationRef.tick() - аналогично Angular 1
$rootScope.$digest()
- т$rootScope.$digest()
Проверить полное дерево компонентов - NgZone.run(callback) - аналогично
$rootScope.$apply(callback)
- т$rootScope.$apply(callback)
Оценивает функцию обратного вызова внутри зоны Angular 2. Я думаю, но я не уверен, что это заканчивается проверкой полного дерева компонентов после выполнения функции обратного вызова. - ChangeDetectorRef.detectChanges() - аналогично
$scope.$digest()
- т.е. проверять только этот компонент и его дочерние элементы
Вам нужно будет импортировать, а затем внедрить ApplicationRef
, NgZone
или ChangeDetectorRef
в ваш компонент.
Для вашего конкретного сценария я бы порекомендовал последний вариант, если изменился только один компонент.
Ответ 2
tx, нашел обходной путь, в котором я нуждался:
constructor(private zone:NgZone) {
// enable to for time travel
this.appStore.subscribe((state) => {
this.zone.run(() => {
console.log('enabled time travel');
});
});
run zone.run заставит компонент повторно выполнить рендеринг
Ответ 3
Подход 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();
}
}
Ответ 4
Другие ответы здесь предоставляют решения для запуска циклов обнаружения изменений, которые обновят представление компонента (что не совпадает с полным повторным рендерингом).
Полный повторный рендеринг, который приведет к уничтожению и повторной инициализации компонента (вызов всех хуков жизненного цикла и перестроение представления), можно выполнить с помощью 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.
Ответ 5
Я принудительно перезагружаю свой компонент, используя * ngIf.
Все компоненты внутри моего контейнера возвращаются к крюкам полного жизненного цикла.
В шаблоне:
<ng-container *ngIf="_reload">
components here
</ng-container>
Тогда в файле ts:
public _reload = true;
private reload() {
setTimeout(() => this._reload = false);
setTimeout(() => this._reload = true);
}
Ответ 6
ChangeDetectorRef.detectChanges()
обычно является наиболее сфокусированным способом сделать это. ApplicationRef.tick()
обычно слишком сложный подход кувалдой.
Чтобы использовать ChangeDetectorRef.detectChanges()
, вам понадобится это вверху вашего компонента:
import { ChangeDetectorRef } from '@angular/core';
... тогда обычно вы называете это псевдонимом, когда вставляете его в свой конструктор следующим образом:
constructor( private cdr: ChangeDetectorRef ) { ... }
Затем в соответствующем месте вы называете это так:
this.cdr.detectChanges();
Место, куда вы звоните ChangeDetectorRef.detectChanges()
, может быть очень важным. Вам необходимо полностью понять жизненный цикл и то, как именно ваше приложение функционирует и отображает его компоненты. Здесь нет альтернативы тому, чтобы полностью выполнить домашнюю работу и убедиться, что вы понимаете жизненный цикл Angular наизнанку. Затем, как только вы поймете это, вы сможете использовать ChangeDetectorRef.detectChanges()
надлежащим образом (иногда очень легко понять, где вы должны его использовать, в других случаях он может быть очень сложным).