由于我们有非常大的Angular 1.x应用程序,我们无法将其完全升级到Angular 2,但我喜欢新架构。版本1.5为旧的相同应用带来了惊人的component
。作为所有很酷的东西,它缺乏文档; - )
所以,这是一个问题。我在控制器的定义中有这两行:
this.$onInit = setType;
this.$onChanges = setType;
第一个是工作,而第二个不工作。我正在使用'<'
绑定。因此,在第一次加载时,组件的状态根据传递的值设置,而更改未反映。我希望它应该从[1]和[2]起作用。
[1] https://docs.angularjs.org/guide/component
[2] https://angular.io/docs/js/latest/api/core/OnChanges-interface.html
UPD 好的,我已经知道它不应该工作: https://github.com/angular/angular.js/issues/14030
有人知道好的解决方法吗?
UPD2 从1.5.3起作用
答案 0 :(得分:24)
从AngularJs 1.5.3开始,假设ctrl.someModel在子组件中单向绑定,以下不会触发$ onChanges。
function get() {
api.getData().then( (data) => {
ctrl.someModel.data = data
}
}
似乎更新对象的属性似乎不会被识别为更新。
这就是我目前如何解决这个问题。我不相信它是最好的解决方案,但它会触发$ onChanges。我创建了我的初始模型的深层副本,将数据添加为其属性之一,然后将我的初始模型设置为新对象的值。本质上,我更新了整个对象,它被生命周期钩子接收:
function get() {
api.getData().then( (data='42') => {
const updatedModel = angular.copy(ctrl.someModel)
updatedModel.data = data
ctrl.someModel = updatedModel
}
}
在子组件中(假设模型被绑定为&#39;数据&#39;):
this.$onInit = function(bindings) {
if (bindings.data && bindings.data.currentValue) {
console.log(bindings.data.currentValue) // '42'
}
}
答案 1 :(得分:14)
处理$onChanges
非常棘手。实际上,这就是为什么在版本1.5.8中他们引入了$doCheck
,类似于Angular 2 ngDoCheck。
通过这种方式,您可以手动收听正在收听的对象 更改不与$onChanges
挂钩一起发生(仅在引用时调用)对象的变化)。同样的事情,但它被称为每个摘要周期,允许您手动检查更改(但比观察更好)。
有关详细信息,请参阅this blog post
答案 2 :(得分:7)
As far as I can tell, both the $onChanges
and $onInit
method should work with AngularJS version 1.5.3.
I've created a plnkr that demonstrates both usages.
It has two components, an outer and an inner component, where a value is bound from the outer to the inner component using the one-way binding operator <
. An input field updates the outer component's value. On every keyboard input into the input field, the $onChanges
method is fired (open your console to see).
angular.module("app", [])
.component("outer", {
restrict: "E",
template: `<input ng-model=$ctrl.value> <br />
<inner value="$ctrl.value">
</inner>`
})
.component("inner", {
restrict: "E",
template: `{{$ctrl.value}}`,
bindings: {
value: "<"
},
controller: function(){
function setType() {
console.log("called");
}
this.$onInit = setType;
this.$onChanges = setType;
}
});
答案 3 :(得分:2)
基本上,$ onChanges角度生命周期钩子触发器当angular找到引用的变化时(不是更改对象中的属性),因此为了调用子节点中的$ onChanges,在父节点中,分配新对象。例如,
angular.module("app", [])
.component("outer", {
restrict: "E",
controller : function(){
this.value = {};
this.userButtonClick = function(someValue){
this.value = angular.copy(someValue);
}
},
template: `<input ng-click="$ctrl.userButtonClick({somevalue : "value"})" />
<br />
<inner value="$ctrl.value">
</inner>`
})
.component("inner", {
restrict: "E",
template: `{{$ctrl.value}}`,
bindings: {
value: "<"
},
controller: function(){
function setType() {
console.log("called");
}
this.$onInit = setType;
this.$onChanges = function(changeObj){
console.log("changed value",changeObj.value.currentValue);
}
}
});
除非你真的想在每个摘要周期中触发回调,否则不要使用$ doCheck,因为无论是否有某些绑定更改,都会在每个$ digest周期中调用它。