1. ホーム
  2. アンギュラー

[解決済み】markForCheck()とdetectChanges()の違いは何ですか?)

2022-04-04 17:46:17

質問

とはどのような違いがあるのでしょうか? ChangeDetectorRef.markForCheck()ChangeDetectorRef.detectChanges() ?

自分だけ SOに関する情報が見つかりました。 との違いについて NgZone.run() この2つの関数の間にはありません。

ドキュメントを参照しただけの回答の場合、どちらかを選択するための実際のシナリオを説明してください。

どのように解決するのですか?

<ブロッククオート

detectChanges() : void

変更検出器とその子をチェックします。

つまり、モデル(クラス)内部が変更されてもビューに反映されていない場合、Angularに通知してその変更を検出(ローカルの変更を検出)し、ビューを更新する必要があるかもしれないのです。

考えられるシナリオは以下の通りです。

1- 変更検出器がビューから切り離されている ( デタッチ )

2- 更新が行われましたが、Angular Zoneの中に入っていないため、Angularはそれについて知りません。

例えば、サードパーティーの関数がモデルを更新し、その後にビューを更新したい場合などです。

 someFunctionThatIsRunByAThirdPartyCode(){
     yourModel.text = "new text";
 }

このコードはAngularの圏外にあるため(おそらく)、変更を検知してビューを更新することを確認する必要がある可能性が最も高いです。

 myFunction(){
   someFunctionThatIsRunByAThirdPartyCode();

   // Let's detect the changes that above function made to the model which Angular is not aware of.
    this.cd.detectChanges();
 }

ノート :

言い換えれば、Angularの変更サイクルの中にその変更を取り込む他の方法があります。

** サードパーティーの関数をzone.runでラップすることができます。

 myFunction(){
   this.zone.run(this.someFunctionThatIsRunByAThirdPartyCode);
 }

** この関数は setTimeout 内でラップすることができます。

myFunction(){
   setTimeout(this.someFunctionThatIsRunByAThirdPartyCode,0);
 }

3- また、モデルを更新した後に change detection cycle が終了した場合、この恐ろしいエラーが発生します。

チェックした後に式が変更されました"。

これは一般的に(Angular2言語から):

私はあなたのモデルで、私が受け入れた方法(イベント、XHRリクエスト、setTimeout、...)の1つによって引き起こされた変更を見ました。そして、あなたのビューを更新するために変更検出を実行し、それを完了しました。

このエラーには必ず出くわします :P .

それを修正するためのいくつかの方法。

1- 正しい方法 : 更新が変更検出サイクルの内側であることを確認してください (Angular2 の更新は一度だけ起こる一方向の流れです。その後モデルを更新せず、より良い場所/時間にコードを移動してください)。

2- 怠惰な方法 これは間違いなく最良の方法ではありませんが、可能なシナリオは何かと聞かれたので、そのうちの1つを紹介します。

この方法は、「あなたが変更検知を実行したことは心から知っているが、あなたがチェックを終えた後、私はその場で何かを更新しなければならなかったので、もう一度実行してほしい」と言いたいのです。

3- コードを setTimeout というのも setTimeout はゾーンによってパッチが適用され detectChanges が終了した後に


ドキュメントより

markForCheck() : void

すべてのChangeDetectionStrategyの先祖をチェックするようにマークします。

これは主に 変更検出ストラテジー である場合、そのコンポーネントは オンプッシュ .

OnPush自体は、これらのいずれかが発生した場合にのみ、変更検知を実行することを意味します。

1- コンポーネントの@Inputの1つが完全に新しい値で置き換えられた場合、または簡単に言えば、@Inputプロパティの参照が完全に変更された場合です。

ですから、もし 変更検出ストラテジー である場合、そのコンポーネントは オンプッシュ そして、あなたは、:

   var obj = {
     name:'Milad'
   };

そして、それを更新/変異させるのです。

  obj.name = "a new name";

を更新しません。 オブジェ を参照するため、変更検出は実行されず、したがってビューには更新/変異が反映されません。

この場合、手動でAngularにビューをチェックし更新するように指示する必要があります(markForCheck)。

だから、あなたがこれをした場合。

  obj.name = "a new name";

する必要があります。

  this.cd.markForCheck();

むしろ、以下のようにすると、変更検出が実行されることになります。

    obj = {
      name:"a new name"
    };

これは、以前の obj を完全に置き換えて、新しい {} ;

2- クリックなどのイベントが発生したか、子コンポーネントのいずれかがイベントを発信しました。

のようなイベント。

  • クリック
  • キー操作
  • サブスクリプションイベント
  • その他

要するに:

  • 使用方法 detectChanges() は、angularが変更検知を実行した後にモデルを更新した場合、もしくは更新がangular worldに全く反映されていない場合です。

  • 使用方法 markForCheck() OnPush を使っていて、かつ ChangeDetectionStrategy の内部でモデルを更新した場合、データを変異させるか、あるいは セットタイムアウト ;