AngularJS 1.5.x $ onChanges不适用于单向绑定更改

mtp*_*ltz 5 angularjs angularjs-components angularjs-1.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);
    };
})
Run Code Online (Sandbox Code Playgroud)

小智 10

不会调用该$onChanges方法来更改对象的子属性.对象的默认更改通常在组件生命周期内遵循此顺序:

  1. UNINITIALIZED_VALUE到 undefined
  2. undefined{}{ someAttribute: someValue, .. }
  3. ({..}undefined,如果你delete在一个父范围的对象)

要查看子属性,您可以使用$doCheck1.5.8中添加的方法.它在每个摘要周期调用,不带参数.拥有权利的同时也被赋予了重大的责任.在该方法中,您将设置检测某个值是否已更新的逻辑 - 新值已在控制器范围内更新,您只需找到一种方法来确定该值是否与先前已知值相比发生了更改.

您可以previousValueOfObjectAttribute在开始期望对此特定属性进行更改之前在控制器上设置变量(例如,当子组件B调用output binding组件A中的函数时,目标对象 - 它是A中输入绑定到B - 的更改).如果在即将发生变化时无法预测,您可以在通过该$doCheck方法观察到任何变化后制作感兴趣的特定属性的副本.

在我的特定用例中,我没有明确地检查旧值和新值,但我使用了promise(store $q.defer().promise),意图是我在$doCheck方法中"成功"观察到的任何更改都将解决该承诺.我的控制器看起来像下面这样:

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);
}
Run Code Online (Sandbox Code Playgroud)

(rt promise.$$state.status,看这篇文章).

对于所有其他意图和目的,观察原始数据类型的更改,您仍应使用$onChanges.参考:https://docs.angularjs.org/guide/component


GBa*_*GBa 4

$onChanges又不是$onChange

此外, onChange 仅在父值更改时更新,而不是子值更改。看看这个笨蛋。请注意,console.log 仅在您输入第一个输入时才会触发。