AngularJS 1.5.x $ onChanges无法使用单向绑定更改

时间:2016-06-04 23:53:25

标签: 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);
    };
})

4 个答案:

答案 0 :(得分:10)

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

  1. UNINITIALIZED_VALUE undefined
  2. undefined{}{ someAttribute: someValue, .. }
  3. {..}undefined,如果delete父范围内的对象)
  4. 为了观看子属性,您可以使用1.5.8中添加的$doCheck方法。它在每个摘要周期调用,不带参数。拥有权利的同时也被赋予了重大的责任。在该方法中,您将设置检测某个值是否已更新的逻辑 - 新值已在控制器范围内更新,您只需找到一种方法来确定该值是否与先前已知值相比发生了更改

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

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

    $doCheck

    (w.r.t。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); }see this post)。

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

答案 1 :(得分:4)

它是$onChanges而不是$onChange

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

答案 2 :(得分:1)

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

只需执行对象的副本就可以触发$ onChanges事件:

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

致@gkalpak的信用

答案 3 :(得分:0)

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

通过这种方式,您可以手动收听正在收听的对象 更改$onChanges挂钩一起发生(仅在引用时调用)对象的变化)。同样的事情,但它被称为每个摘要周期,允许您手动检查更改(但比观察更好)。

有关详细信息,请参阅this blog post