考虑这个plunker
注意:要观察在输入链接后重新运行应用程序所需的效果
import {Component, OnInit, Input, OnChanges, DoCheck} from 'angular2/core'
@Component({
selector: 'sub',
template: `
<li *ngFor="#elem of sub_list">
<div>{{elem['name']}}</div>
</li>
`
})
export class Sub {
@Input()
sub_list: Object[];
ngOnInit(){
console.log('init');
console.log(this.sub_list);
}
ngOnChanges(){
console.log('change');
console.log(this.sub_list);
}
ngDoCheck() {
console.log('check');
console.log(this.sub_list);
}
}
@Component({
selector: 'my-app',
template: `
<div>
<sub
[sub_list]="my_list"
>
</sub>
</div>
`,
directives: [Sub]
})
export class App {
my_list: Object[] = [];
ngOnInit() {
var vm = this;
setTimeout(function() {
for(var i = 0; i < 100; i++) {
vm.my_list.push({
'index' : i,
'name' : i
});
}
}, 100);
}
}
如果我尝试在this.sub_list
的{{1}}中打印Sub
,则浏览器会输出一个空列表。
但是我们可以看到ngOnChange
仍能正确捕获更改。
这是否有特定原因?
答案 0 :(得分:4)
在您的情况下,不会在阵列上调用ngOnChanges进行更新。事实上,Angular2会根据引用检测更新。我的意思是如果整个数组的引用没有改变(使用push方法在其中添加元素的情况),则不会调用ngOnChanges方法。
在你的情况下,当调用ngOnChanges时你的数组为null,因为它在设置input元素之前被调用。
在这种情况下,有两种方法可以检测到变化:
使用slice(推送后)或concat等方法更新整个数组引用。
this.myArray.push({...});
this.myArray.push = this.myArray.push.slice();
利用ngDoCheck方法和IterableDiffers类手动检查更新。该类允许您注册回调,以便在数组中添加(或删除)元素时得到通知。
有关详细信息,请参阅以下链接:
答案 1 :(得分:1)
好的,我已经知道了。使用空数组初始化类字段时会触发ngOnChange
,然后在超时回调中更新数组,并且未检测到Thierry正确指向的更改。
Angular包含可以跟踪应用中所有异步事件的zone.js库。 Zone检测到某处执行了超时回调并触发ngDoCheck
循环并获得正确的日志。
请参阅plunkr