【发布时间】:2016-01-30 18:22:44
【问题描述】:
如何在 Angular 2 中强制组件重新渲染? 出于调试目的,我想强制一个组件重新渲染它的视图,这可能吗?
【问题讨论】:
-
“重新渲染”是什么意思。更新绑定?
-
只是一个简单的问题,为什么需要强制重新渲染?
标签: angular angular2-changedetection
如何在 Angular 2 中强制组件重新渲染? 出于调试目的,我想强制一个组件重新渲染它的视图,这可能吗?
【问题讨论】:
标签: angular angular2-changedetection
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();
}
}
【讨论】:
在更改检测后进行渲染。要强制进行更改检测,以便将已更改的组件属性值传播到 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 上下文。
pure:false。它可以工作,但对于我的用例来说太昂贵(效率低下)。
我使用 *ngIf 强制重新加载我的组件。
我容器中的所有组件都返回到完整的生命周期钩子。
在模板中:
<ng-container *ngIf="_reload">
components here
</ng-container>
然后在ts文件中:
public _reload = true;
private reload() {
setTimeout(() => this._reload = false);
setTimeout(() => this._reload = true);
}
【讨论】:
setTimeout(),我什么都有。现在我正在使用一个简单而轻量级的解决方案!
tx,找到了我需要的解决方法:
constructor(private zone:NgZone) {
// enable to for time travel
this.appStore.subscribe((state) => {
this.zone.run(() => {
console.log('enabled time travel');
});
});
running zone.run 将强制组件重新渲染
【讨论】:
此处的其他答案提供了触发更改检测周期的解决方案,这些周期将更新组件的视图(这与完全重新渲染不同)。
可以通过使用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()(有时很容易理解你应该在哪里使用它,有时它可能非常复杂)。
【讨论】: