我不明白为什么在更改输入中的绑定基元时没有启动$ 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);
};
})
答案 0 :(得分:10)
$onChanges
方法 not 调用对象子属性的更改。对象的默认更改通常在组件生命周期内遵循此顺序:
undefined
undefined
至{}
或{ someAttribute: someValue, .. }
{..}
至undefined
,如果delete
父范围内的对象)为了观看子属性,您可以使用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。