5

入力でバインドされたプリミティブを変更したときに $onChanges が開始されない理由がわかりません。誰かが私が間違ったことを見て、これを簡単な方法で説明できますか? 実際のアプリケーションでも動作させることができなかったので、簡単なテスト アプリケーションのplunkrを作成しました。

angular
.module('test', [])
.component('test', {

    template: '<child application="vm.application"></child>',
    controller: 'testCtrl as vm'
})
.controller('testCtrl', function() {

    var vm = this;  

    vm.$onInit = function () {

        vm.application = {
            data: {
                name: 'Test'
            }
        }
    };
})
.component('child', {

    template: '<input type="text" ng-model="vm.application.data.name">',
    bindings: {
        application: '<'
    },
    controller: 'childCtrl as vm'
})
.controller('childCtrl', function() {

    var vm = this;

    vm.$onChanges = function (changes) {
        console.log('CHANGED: ', changes);
    };
})
4

4 に答える 4

10

この$onChangesメソッドは、オブジェクトのサブプロパティの変更に対しては呼び出されません。通常、オブジェクトに対するデフォルトの変更は、コンポーネントの有効期間内で次の順序に従います。

  1. UNINITIALIZED_VALUE からundefined
  2. undefined{}または_{ someAttribute: someValue, .. }
  3. (親スコープ内のオブジェクトの{..}場合undefined)delete

$doCheckサブプロパティを監視するには、1.5.8 で追加されたメソッドを使用できます。ダイジェスト サイクルごとに呼び出され、パラメーターは必要ありません。大きな力には大きな責任が伴います。そのメソッドでは、特定の値が更新されたかどうかを検出するロジックを配置します。新しい値はコントローラーのスコープで既に更新されているため、値が以前の既知の値と比較して変更されたかどうかを判断する方法を見つける必要があります。 .

previousValueOfObjectAttributeこの特定の属性への変更を期待し始める前に、コントローラーに変数を設定できます (たとえば、サブコンポーネント B がoutput bindingコンポーネント A の関数を呼び出すとき、それに基づいて、A のターゲット オブジェクト (B への入力バインド) が変更されます)。変更がいつ発生するか予測できない場合は、$doCheckメソッドを介して変更が観察された後に、関心のある特定の属性のコピーを作成できます。

私の特定のユースケースでは、古い値と新しい値を明示的にチェックしませんでしたが$q.defer().promise、メソッドで「正常に」観察される変更が$doCheckその約束を解決するという意図で、約束 ( store ) を使用しました。私のコントローラーは次のようになりました。

dn.$doCheck = function () {
  if (dn.waitForInputParam &&
      dn.waitForInputParam.promise.$$state.status === 0 &&
      dn.targetObject.targetAttribute !== false)
    dn.waitForInputParam.resolve(dn.targetObject.targetAttribute);
}

dn.listenToInputChange = function () {
  dn.waitForInputParam = $q.defer();
  dn.waitForInputParam.promise.then(dn.onInputParamChanged);
}

dn.onInputParamChanged = function (value) {
  // do stuff
  //

  // start listening again for input changes -- should be async to prevent infinite $digest loop
  setTimeout(dn.listenToInputChange, 1);
}

(wrt promise.$$state.statusこの投稿を参照)。

他のすべての意図と目的のために、プリミティブ データ型への変更を監視するには、引き続き を使用する必要があります$onChanges。参照: https://docs.angularjs.org/guide/component

于 2016-08-12T19:40:00.833 に答える
0

扱い$onChangesがややこしい。実際、それがバージョン 1.5.8 で$doCheckAngular 2 ngDoCheck に似た を導入した理由です。

このようにして、リッスンされているオブジェクトの変更を手動でリッスンできますが、これはフックでは発生しません(オブジェクトの参照が変更された場合にのみ呼び出されます)。$onChanges同じことですが、すべてのダイジェスト サイクルで呼び出され、手動で変更を確認できます (ただし、監視するよりも優れています)。

詳細については、このブログ投稿を参照してください。

于 2017-02-07T22:34:04.950 に答える