Angular.js: コントローラーは順序をフックします($ onInitの前に$ onChangesが呼び出されます)

作成日 2016年12月16日  ·  9コメント  ·  ソース: angular/angular.js

機能をリクエストしバグを報告しますか?
欲しいのかバグなのかわからない

現在の動作は何ですか?
最初の$onChanges呼び出しは、 $onInit呼び出しの前に行われます。
Angular 1.6のデフォルト構成(preassign = false)では、コンストラクターでバインディングにまだアクセスできないため、 $onInit関数でコントローラーの状態を初期化することをお勧めします。

期待される動作は何ですか?
最初に$onInitを呼び出す方が論理的だと思います。
コントローラが完全に初期化されていない間、Angularは何もするべきではありません。

行動を変える動機/ユースケースは何ですか?
$onChanges関数の$onInit関数で作成されることになっているオブジェクトを使用する場合。 コントローラがまだ初期化されていないため、最初の呼び出しでエラーが発生します。
解決策は、コンストラクター内でこれらのオブジェクトを初期化することですが、コントローラーを2つの異なる場所で初期化します...

この問題の影響を受けるAngularのバージョンとブラウザ/ OSはどれですか? また、最新の安定版とスナップショット(https://code.angularjs.org/snapshot/)バージョンでテストしてください。
角度1.6バージョン

works as expected

最も参考になるコメント

これは(主にAngular 2+の動作に一致させるために)意図されています。 あなたはそれを見逃している場合、あなたはそれが最初の(事前$のOnInit)の呼び出しであるかどうかを確認することができます$onChangesの戻り値チェックすることで、 isFirstChange()のいずれかの方法SimpleChangeオブジェクト:

{
  ...
  bindings: {foo: '<'},
  controller: function SomeController() {
    this.$onChanges = function(changes) {
      if (changes.foo.isFirstChange()) {
        // `$onInit()` has not been called yet...
      }
    };
  }
}

私の最初の反応は同じだったことを認めます。 メンタルモデルの観点からは、 $onInit()がコントローラーで最初に発生することであると考える方が簡単です。 次に$onChanges()$onChanges()$onChanges() 、最後に$onDestroy()

しかし、考えてみれば、 $onInit呼び出す前に、バインディングを評価してコントローラーインスタンスに割り当てる必要があります。 そうすることで、(以前は定義されていなかった)値の変更が検出され、 $onChanges介して報告する必要があります。

これは期待どおりに機能しているため(または少なくとも意図したとおりに:wink :)終了します。

全てのコメント9件

これは(主にAngular 2+の動作に一致させるために)意図されています。 あなたはそれを見逃している場合、あなたはそれが最初の(事前$のOnInit)の呼び出しであるかどうかを確認することができます$onChangesの戻り値チェックすることで、 isFirstChange()のいずれかの方法SimpleChangeオブジェクト:

{
  ...
  bindings: {foo: '<'},
  controller: function SomeController() {
    this.$onChanges = function(changes) {
      if (changes.foo.isFirstChange()) {
        // `$onInit()` has not been called yet...
      }
    };
  }
}

私の最初の反応は同じだったことを認めます。 メンタルモデルの観点からは、 $onInit()がコントローラーで最初に発生することであると考える方が簡単です。 次に$onChanges()$onChanges()$onChanges() 、最後に$onDestroy()

しかし、考えてみれば、 $onInit呼び出す前に、バインディングを評価してコントローラーインスタンスに割り当てる必要があります。 そうすることで、(以前は定義されていなかった)値の変更が検出され、 $onChanges介して報告する必要があります。

これは期待どおりに機能しているため(または少なくとも意図したとおりに:wink :)終了します。

答えてくれてありがとう、今はもっとはっきりしています:)

これは意図的なものだと理解しています。$ onInit()内に$ onChanges()関数の定義を登録するとどうでしょうか。

@ bharatpatil 、AngularJS(1.x。)で機能するはずですが、Angular(2+)では機能しません。

if(changes.foo.isFirstChange()){
// $onInit()はまだ呼び出されていません...
}

@gkalpakこの議論は間違っていると思います。 binding.isFirstChange()メソッドは、関連するバインディングが最初に呼び出されたことを保証するだけです。 サービス呼び出しの後に初期化されるバインディングに時間がかかりすぎると考えてください。 この状況では、 controller.$onChangesメソッドの前にcontroller.$onInitメソッドを呼び出す必要があります。 私が間違っている?

バインディングの先頭には常に値があり( undefined場合もあります)、これは事前に初期化された値とは常に異なります。 したがって、 $onChanges()常にで呼び出されますchanges.fooを呼び出す前に$onInit()

バインディングが初期化される前に値を持つことができることは論理的に意味がありません。 これが、初期化という単語の辞書での定義です(初期値を設定します)。 初期値がない場合は変更できません。 ここでは名前がすべて間違っていて不自然だと思います。

次のようなコードを書くことを余儀なくされなかった状況を思い出せません。

$onChanges(changesObj: { [index: string]: angular.IChangesObject; })  {
   if (!this.isInitialized) return;
   ...
}

「初期化」の前に「変更」を呼び出すことは意味がありません。

Angularのコースと同等です...変更前にinitが発生することを誰もが期待するのはなぜですか?

このページは役に立ちましたか?
0 / 5 - 0 評価