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. (如果您是父范围内的对象{..}undefineddelete

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

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

在我的特定用例中,我没有明确检查新旧值之间的关系,但我使用了一个承诺(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);
}

(写promise.$$state.status见这篇文章)。

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

于 2016-08-12T19:40:00.833 回答
4

$onChanges和不是$onChange

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

于 2016-06-05T00:27:41.540 回答
1

正如上面其他人所说,Angular 不会监视对象属性的变化,但是,您可以让 Angular 相信您的对象是通过引用更改的。

为了触发 $onChanges 事件,对对象进行 拷贝就足够了:

vm.campaign = angular.extend({}, vm.campaign);

归功于@gkalpak

于 2017-11-07T16:35:46.583 回答
0

处理$onChanges是棘手的。实际上,这就是为什么他们在 1.5.8 版中引入了$doCheck类似于 Angular 2 ngDoCheck 的 .

这样,您可以手动侦听正在侦听的对象内部的更改,而挂钩不会发生这种情况$onChanges(仅当对象的引用发生更改时才调用)。它是相同的东西,但它会在每个摘要循环中调用,允许您手动检查更改(但比监视更好)。

有关更多详细信息,请参阅此博客文章

于 2017-02-07T22:34:04.950 回答