変更を表示するために、以下のコードにmarkForCheck()を追加する必要がある理由がよくわかりません。@Input()が変更検出をトリガーしないのはなぜですか?
プロジェクトをOnPushにリファクタリングしています。これら2つのコンポーネントは両方ともOnPushが有効になっています。私が理解しているように、これが有効になっていて、Input()が変更されると(のようにmessages
)、変更検出がトリガーされます。
以下のコードでは、を介して電話をかけますgraphqlService
。呼び出しを受信すると、着信データを解析してから、informationMessages
プロパティに設定cv-messages
しmessages
ます。プロパティは、プロパティを介して子コンポーネントにバインドされます。
その結果ngOnChanges
、informationMessages
プロパティが初期化されるときに、関数は1回だけ呼び出されます。ただし、最終的に解析されたデータがそれに設定されている場合はそうではありません。
markForCheck()を追加すると、正常に機能します。
次のようなテンプレートを使用して、この親コンポーネントについて考えてみます。
<cv-messages [messages]="informationMessages"></cv-messages>
そして、このコードを含むタイプスクリプトファイル:
informationMessages: InformationMessageType[] = [];
ngOnInit() {
this.graphqlService.loadInformationMessages().subscribe(data => {
const informationMessages: InformationMessageType[] = data;
.... // parsing stuff
this.informationMessages = informationMessages;
// add markForCheck() here
});
}
メッセージコンポーネントには、次のようなngOnChanges関数があります。
ngOnChanges(changes) {
console.log(this.constructor.name ' CHANGE:', changes);
}
更新:
以下の回答のコメントで解決策を見つけることができます。基本的に、変更が非同期的に変更された場合、変更検出はトリガーされません@Input()
。したがって、その場合markForCheck()
、変更検出を強制するためにを追加する必要があります。
ビューがOnPush(checkOnce)変更検出戦略を使用する場合、ビューを変更済みとして明示的にマークして、再度チェックできるようにします。
通常、入力が変更されたとき、またはビューでイベントが発生したときに、コンポーネントはダーティ(再レンダリングが必要)としてマークされます。このメソッドを呼び出して、これらのトリガーが発生していなくてもコンポーネントがチェックされるようにします。
したがって、このメソッドは、コンポーネントをダーティとしてマークして再レンダリングするために必要です。
更新:
2つのタイプがありますChangeDetectionStrategy
:
OnPush:0 CheckOnceストラテジーを使用します。これは、ストラテジーをデフォルト(CheckAlways)に設定することにより、再アクティブ化されるまで自動変更検出が非アクティブ化されることを意味します。変更検出は引き続き明示的に呼び出すことができます。この戦略はすべての子ディレクティブに適用され、オーバーライドすることはできません。
デフォルト:1デフォルトのCheckAlways戦略を使用します。この戦略では、明示的に非アクティブ化されるまで変更検出が自動的に行われます。
したがって、を使用するとOnPush
、自動変更検出が無効になり、ビューを変更済みとしてマークして、再度確認できるようにする必要があります。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加