Angular 2でコンポーネントを強制的に再レンダリングする方法デバッグ目的でReduxを使って作業している場合、コンポーネントにビューの再レンダリングを強制したいのですが、可能でしょうか。
レンダリングは変更検出後に行われます。変更の検出を強制するために、変更されたコンポーネントプロパティ値がDOMに伝達されるようにします(そしてブラウザはそれらの変更をビューに表示します)。
$rootScope.$digest()
と同様 - つまり、完全なコンポーネントツリーをチェックする$rootScope.$apply(callback)
と同様 - つまり、Angular 2ゾーン内でコールバック関数を評価私は思うが、これがコールバック関数を実行した後に完全なコンポーネントツリーをチェックすることになることは確かではない。$scope.$digest()
と同様 - つまり、このコンポーネントとその子のみをチェックするインポートしてからApplicationRef
、NgZone
、またはChangeDetectorRef
をコンポーネントに注入する必要があります。
特定のシナリオでは、1つのコンポーネントだけが変更された場合は最後のオプションをお勧めします。
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();
}
}
ここでの他の答えは、コンポーネントのビューを更新する変更検出サイクルをトリガーするための解決策を提供します(これは完全な再レンダリングと同じではありません)。
次のように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 。
* ngIfを使用してコンポーネントを強制的にリロードします。
コンテナ内のすべてのコンポーネントは、ライフサイクル全体のフックに戻ります。
テンプレートで:
<ng-container *ngIf="_reload">
components here
</ng-container>
次に、tsファイルで:
public _reload = true;
private reload() {
setTimeout(() => this._reload = false);
setTimeout(() => this._reload = true);
}
通常、ChangeDetectorRef.detectChanges()
がこれに最も焦点を絞った方法です。 ApplicationRef.tick()
は通常、大胆なアプローチです。
ChangeDetectorRef.detectChanges()
を使用するには、コンポーネントの上部にこれが必要です。
import { ChangeDetectorRef } from '@angular/core';
...その後、通常、コンストラクタに次のように注入するときにエイリアスを作成します。
constructor( private cdr: ChangeDetectorRef ) { ... }
次に、適切な場所で、次のように呼び出します:
this.cdr.detectChanges();
WhereChangeDetectorRef.detectChanges()
を呼び出すことは非常に重要です。ライフサイクルと、アプリケーションがどのように機能し、コンポーネントをレンダリングするかを正確に理解する必要があります。宿題を完全に行い、Angularライフサイクルを完全に理解することの代わりになるものはありません。次に、それを理解したら、ChangeDetectorRef.detectChanges()
を適切に使用できます(使用する場所を非常に簡単に理解できる場合もあれば、非常に複雑になる場合もあります)。