我知道我不是第一个问这个问题的人,但我在之前的问题中找不到答案。我在一个组件中有这个
<div class="col-sm-5">
<laps
[lapsData]="rawLapsData"
[selectedTps]="selectedTps"
(lapsHandler)="lapsHandler($event)">
</laps>
</div>
<map
[lapsData]="rawLapsData"
class="col-sm-7">
</map>
在 Controller 中
rawLapsdata
会不时发生变异。在
laps
中,数据以表格格式输出为 HTML。每当 rawLapsdata
更改时,它就会更改。我的
map
组件需要使用 ngOnChanges
作为触发器来重绘谷歌 map 上的标记。问题是当 rawLapsData
在父级中更改时 ngOnChanges 不会触发。我能做什么?import {Component, Input, OnInit, OnChanges, SimpleChange} from 'angular2/core';
@Component({
selector: 'map',
templateUrl: './components/edMap/edMap.html',
styleUrls: ['./components/edMap/edMap.css']
})
export class MapCmp implements OnInit, OnChanges {
@Input() lapsData: any;
map: google.maps.Map;
ngOnInit() {
...
}
ngOnChanges(changes: { [propName: string]: SimpleChange }) {
console.log('ngOnChanges = ', changes['lapsData']);
if (this.map) this.drawMarkers();
}
更新: ngOnChanges 不起作用,但看起来 lapsData 正在更新。在 ngInit 中是一个用于缩放更改的事件监听器,它也调用
this.drawmarkers
。当我更改缩放比例时,我确实看到标记发生了变化。所以唯一的问题是我在输入数据更改时没有收到通知。在 parent 中,我有这条线。 (回想一下,变化反射(reflect)在圈数中,而不是在 map 中)。
this.rawLapsData = deletePoints(this.rawLapsData, this.selectedTps);
并注意
this.rawLapsData
本身就是一个指向大型 json 对象中间的指针this.rawLapsData = this.main.data.TrainingCenterDatabase.Activities[0].Activity[0].Lap;
最佳答案
rawLapsData
继续指向同一个数组,即使您修改了数组的内容(例如,添加项目、删除项目、更改项目)。
在变更检测期间,当 Angular 检查组件的输入属性是否有变更时,它(本质上)使用 ===
进行脏检查。对于数组,这意味着数组引用(仅)是脏检查的。由于 rawLapsData
数组引用未更改,因此不会调用 ngOnChanges()
。
我可以想到两种可能的解决方案:
ngDoCheck()
并执行您自己的更改检测逻辑以确定数组内容是否已更改。 (生命周期钩子(Hook)文档有 an example 。) rawLapsData
分配一个新数组。然后 ngOnChanges()
将被调用,因为数组(引用)将显示为更改。 在您的回答中,您提出了另一种解决方案。
在 OP 上重复一些评论:
laps
组件中,您的代码/模板循环遍历 lapsData
数组中的每个条目,并显示内容,因此显示的每条数据都有 Angular 绑定(bind)。 ===
检查),它仍然(默认情况下)对所有模板绑定(bind)进行脏检查。当其中任何一个发生变化时,Angular 将更新 DOM。这就是你所看到的。 maps
组件的模板中可能没有任何绑定(bind)到其 lapsData
输入属性,对吗?这将解释差异。 请注意,两个组件中的
lapsData
和父组件中的 rawLapsData
都指向同一个/一个数组。因此,即使 Angular 没有注意到 lapsData
输入属性的任何(引用)更改,组件“获取”/查看任何数组内容也会发生更改,因为它们都共享/引用该数组。我们不需要 Angular 来传播这些更改,就像我们使用原始类型(字符串、数字、 bool 值)一样。但是对于原始类型,对值的任何更改都将始终触发 ngOnChanges()
——这是您在答案/解决方案中利用的东西。正如您现在可能已经发现的那样,对象输入属性与数组输入属性具有相同的行为。
关于Angular2 变化检测 : ngOnChanges not firing for nested object,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/45132017/