Javascript Angular 1.5 组件 onChanges 不起作用
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/35604919/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Angular 1.5 component onChanges is not working
提问by leitasat
Since we have pretty big Angular 1.x application, we can't upgrade it fully to Angular 2 but I love the new architecture. Version 1.5 brings amazing component
s to the old same app. As all cool stuff, it lacks documentation ;-)
由于我们有相当大的 Angular 1.x 应用程序,我们无法将其完全升级到 Angular 2,但我喜欢新架构。1.5 版为component
旧的同一个应用程序带来了惊人的s。和所有很酷的东西一样,它缺少文档;-)
So, here is a question. I have those two lines in the controller's definition:
所以,这里有一个问题。我在控制器的定义中有这两行:
this.$onInit = setType;
this.$onChanges = setType;
the first is working, whilst the second isn't. I am using '<'
binding. So on the first load, the component's state is set according to passed values, whilst the changes are not being reflected. I got the hope that it should work from [1] and [2].
第一个有效,而第二个无效。我正在使用'<'
绑定。所以在第一次加载时,组件的状态是根据传递的值设置的,而不会反映更改。我希望它应该从 [1] 和 [2] 开始工作。
[1] https://docs.angularjs.org/guide/component
[1] https://docs.angularjs.org/guide/component
[2] https://angular.io/docs/js/latest/api/core/OnChanges-interface.html
[2] https://angular.io/docs/js/latest/api/core/OnChanges-interface.html
UPDOk, I have learnt that it is not supposed to work: https://github.com/angular/angular.js/issues/14030
UPD好的,我了解到它不应该工作:https: //github.com/angular/angular.js/issues/14030
Does anybody know good workarounds?
有人知道好的解决方法吗?
UPD2It works as of 1.5.3
UPD2从 1.5.3 开始工作
回答by Jonathan Dupré
As of AngularJs 1.5.3, supposing ctrl.someModel is bound one-way in a child component, the following won't trigger $onChanges.
从 AngularJs 1.5.3 开始,假设 ctrl.someModel 在子组件中单向绑定,以下不会触发 $onChanges。
function get() {
api.getData().then( (data) => {
ctrl.someModel.data = data
}
}
It seems like updating properties of an object won't be recognized as an update.
似乎更新对象的属性不会被识别为更新。
This is how I currently get around it. I don't believe it to be the best solution, but it triggers $onChanges. I create a deep copy of my initial model, add the data as one of it's properties, and then set my initial model to the value of the new object. Essentially, I update the whole object, which is picked up by the lifecycle hook:
这就是我目前解决它的方式。我不相信它是最好的解决方案,但它会触发 $onChanges。我创建了初始模型的深层副本,将数据添加为它的属性之一,然后将初始模型设置为新对象的值。本质上,我更新了整个对象,它被生命周期钩子拾取:
function get() {
api.getData().then( (data='42') => {
const updatedModel = angular.copy(ctrl.someModel)
updatedModel.data = data
ctrl.someModel = updatedModel
}
}
And in the child component (assuming the model as been binded as 'data'):
在子组件中(假设模型被绑定为“数据”):
this.$onInit = function(bindings) {
if (bindings.data && bindings.data.currentValue) {
console.log(bindings.data.currentValue) // '42'
}
}
回答by Z. Khullah
Dealing with $onChanges
is tricky. Actually, thats why in version 1.5.8 they introduced the $doCheck
, similar to Angular 2 ngDoCheck.
处理起来$onChanges
很棘手。实际上,这就是为什么他们在 1.5.8 版本中引入了$doCheck
,类似于 Angular 2 ngDoCheck。
This way, you can manually listen to changes insidethe object being listened, which does notoccur with the $onChanges
hook (called only when the reference of the object is changed). Its the same thing, but it gets called for every digest cycleallowing you to check for changes manually (but better then watches).
这样,您可以手动监听被监听对象内部的变化,而钩子不会发生这种变化$onChanges
(仅在对象的引用发生变化时调用)。它是一样的东西,但它在每个摘要周期都会被调用,允许您手动检查更改(但比监视更好)。
For more details, see this blog post
有关更多详细信息,请参阅此博客文章
回答by KwintenP
As far as I can tell, both the $onChanges
and $onInit
method should work with AngularJS version 1.5.3.
据我所知,$onChanges
和$onInit
方法都应该适用于 AngularJS 1.5.3 版。
I've created a plnkr that demonstrates both usages.
我创建了一个plnkr 来演示这两种用法。
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).
它有两个组件,一个外部组件和一个内部组件,其中使用单向绑定运算符将一个值从外部组件绑定到内部组件<
。输入字段更新外部组件的值。在输入字段中的每个键盘输入时,$onChanges
都会触发该方法(打开控制台查看)。
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;
}
});
回答by sanjeev bhusal
Basically, $onChanges angular lifecycle hook trigger when angular find the change in reference ( not the property in the changed object ), so in order to invoke the $onChanges in the child, in the parent, assign the new object. for example,
基本上, $onChanges angular 生命周期钩子在 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);
}
}
});
Don't use $doCheck unless you really want to trigger a callback in every digest cycle, because it is invoked in every $digest cycle no matter some binding change or not.
不要使用 $doCheck 除非你真的想在每个摘要循环中触发一个回调,因为它会在每个 $digest 循环中调用,无论绑定是否发生变化。