我有一个使用 ajax 请求检索对象数组的父组件。
该组件有两个子组件:一个以树结构显示对象,另一个以表格格式呈现其内容。父级通过 @input 属性将数组传递给他们的子级,他们会正确显示内容。一切都如预期。
当您更改对象中的某些字段时会出现问题:子组件不会收到这些更改的通知。仅当您手动将数组重新分配给其变量时才会触发更改。
我习惯使用 Knockout JS,我需要获得类似于 observableArrays 的效果。
我读过一些关于 DoCheck 的内容,但我不确定它是如何工作的。
我有一个使用 ajax 请求检索对象数组的父组件。
该组件有两个子组件:一个以树结构显示对象,另一个以表格格式呈现其内容。父级通过 @input 属性将数组传递给他们的子级,他们会正确显示内容。一切都如预期。
当您更改对象中的某些字段时会出现问题:子组件不会收到这些更改的通知。仅当您手动将数组重新分配给其变量时才会触发更改。
我习惯使用 Knockout JS,我需要获得类似于 observableArrays 的效果。
我读过一些关于 DoCheck 的内容,但我不确定它是如何工作的。
OnChanges 只有当输入属性的实例发生变化时,生命周期钩子才会触发。
如果要检查输入数组中的某个元素是否已添加、移动或删除,可以在Lifecycle Hook 中使用IterableDiffersDoCheck,如下所示:
constructor(private iterableDiffers: IterableDiffers) {
this.iterableDiffer = iterableDiffers.find([]).create(null);
}
ngDoCheck() {
let changes = this.iterableDiffer.diff(this.inputArray);
if (changes) {
console.log('Changes detected!');
}
}
如果需要检测数组内对象的变化,则需要遍历所有元素,并为每个元素应用KeyValueDiffers。(您可以与之前的检查并行执行此操作)。
访问这篇文章了解更多信息:在 Angular2 中检测数组内对象的变化
您始终可以通过将数组与空数组合并来创建对该数组的新引用:
this.yourArray = [{...}, {...}, {...}];
this.yourArray[0].yourModifiedField = "whatever";
this.yourArray = [].concat(this.yourArray);
上面的代码将更改数组引用,并触发子组件中的 OnChanges 机制。
阅读以下文章,不要错过可变对象和不可变对象。
关键问题是你改变了数组元素,而数组引用保持不变。Angular2 更改检测仅检查数组引用以检测更改。在了解了不可变对象的概念后,您就会明白为什么会遇到问题以及如何解决它。
我在我的一个项目中使用 redux store 来避免此类问题。
https://blog.thoughtram.io/angular/2016/02/22/angular-2-change-detection-explained.html
您可以使用IterableDiffers
constructor(private _differs: IterableDiffers) {}
ngOnChanges(changes: SimpleChanges): void {
if (!this._differ && value) {
this._differ = this._differs.find(value).create(this.ngForTrackBy);
}
}
ngDoCheck(): void {
if (this._differ) {
const changes = this._differ.diff(this.ngForOf);
if (changes) this._applyChanges(changes);
}
}
这似乎已经回答了。然而,对于未来的问题寻求者,我想添加一些在我研究和调试我遇到的变更检测问题时遗漏的东西。现在,我的问题有点孤立,无可否认,这是我的一个愚蠢的错误,但仍然相关。当您更新参考中Array或Object参考中的值时,请确保您处于正确的范围内。我通过使用将自己置于陷阱中setInterval(myService.function, 1000),在那里myService.function()将更新我在服务之外使用的公共数组的值。这实际上从未更新数组,因为绑定已关闭,正确的用法应该是setInterval(myService.function.bind(this), 1000). 我浪费了时间尝试更改检测技巧,当时这是一个愚蠢/简单的错误。在尝试变更检测解决方案之前消除范围作为罪魁祸首;它可能会为您节省一些时间。