4

Angular 2 の変更検出は単方向であり、コンポーネント ツリーの上から下に向かっており、1 回のパスで安定すること、つまり複数の変更検出サイクルがないことを読みました。これらの仮定を考えると、相互に依存するプロパティを持つ親コンポーネントと子コンポーネントがある状況ではどうなるでしょうか? 例:

  1. ユーザー イベントに基づいて、親コンポーネントが子コンポーネントのプロパティを更新します。
  2. この更新により、親のプロパティを更新する子コンポーネントでイベントが発生します
  3. 親プロパティの更新により、子コンポーネントを更新する別のイベントが発生します
  4. ...

私の理解では、Angular 1 での同様の状況は、これらの相互依存するプロパティによってトリガーされるサイクル数に制限を設定することで解決されました。これにより、フレームワークがエラーをスローします。

Angular 2 ではどのように解決されますか? 上記の例のどの時点で変更検出が実際にトリガーされますか?

4

3 に答える 3

9

私はAngular 2の変更検出を読みました...単一のパスの後に安定します

Angular 2 は「安定しません」。Angular 2 アプリでは、1 回のパスで常に安定するようにアプリを作成する必要があります。

デフォルトでは (たとえば、OnPushどのコンポーネントでも変更検出戦略を使用しておらず、どのコンポーネントもdetach()していない場合)、変更検出は次のように機能します。

  • Zone.js モンキー パッチが適用された非同期イベント ((click)イベント、XHR 応答、setTimeout()タイマーなど) が発生します。そのイベントに関連付けられたコールバックが実行され、アプリ内のビューまたはアプリケーション データが変更される可能性があります。次に、モンキーパッチにより、角度変化検出が実行されます。つまり、デフォルトでは (たとえば、変更検出を手動でトリガーしていない場合)、モンキー パッチが適用された非同期イベントのみが変更検出をトリガーします。
  • ルート コンポーネントから開始し、コンポーネント ツリーをたどって (深さ優先トラバーサル)、各データ バインディングの変更がチェックされます。変更が見つかった場合、その変更は「伝播」されます。テンプレート バインディング タイプによっては、伝播が発生する場合があります。
    • 変更された値を DOM に伝播します。たとえば、{{}}バインディングを使用すると、新しい値がtextContent適切な DOM 要素のプロパティに伝達されます。
    • 変更された値を子コンポーネントに伝播します。たとえば、入力プロパティ バインディング ( [childInputProperty]="parentProperty") を使用すると、新しい値が子入力プロパティに伝達されます。
  • 開発モードの場合、すべてのコンポーネントが再度ダーティ チェックされますが、伝播は行われません。この 2 番目のダーティ チェックは、コードの問題を見つけるのに役立ちます。たとえば、バインディングの 1 つ (そのテンプレート式) に副作用があることを示す巧妙な方法であるべき等規則に違反した場合などです。つまり、追加の開発モード チェックにより、1 回のパス後にコードが安定していないかどうかがわかります。

Angular 2 では、副作用は許可されていません。したがって、質問に関連して、子コンポーネントは、入力プロパティの伝播の結果として親プロパティを変更してはなりません。したがって、Angular 2 は、あなたが尋ねた状況を許可しないことで「解決」したと言えます。

これは、聞こえるほど悪くはありません。入力プロパティの伝播が親プロパティを変更できることを私が認識している唯一の方法は、親がそのテンプレートに表示する別のプロパティを変更する入力プロパティのセッター メソッドを子コンポーネントが実装する場合です。(これは、これを行う古いプランカーです。方法を参照してください@Input set backdoor()。) 通常、これを行うことはありません。これを行う必要がある場合は、Günter のコメントが適切です: a 内で変更を行いますsetTimeout()。したがって、次の変更検出サイクルの一部になります。

もう一度強調したいのは、イベント ハンドラーは変更検出の前に実行されるため、アプリ内の任意のデータ (ローカル/コンポーネント ビュー データ、アプリケーション データなど)を自由に変更できるということです。したがって、イベント ハンドラーでは、子コンポーネントは親データを自由に変更できます。たとえば、親と子の両方が同じ配列への参照を持っているとします。イベント ハンドラーが実行されると、親コンポーネントや子コンポーネントはその配列を変更できます。

したがって、イベント ハンドラを変更しても問題ありません。セッターが奇妙なことをした場合にのみ問題があります。

于 2016-06-04T15:47:34.650 に答える