我知道我不是第一个问这个问题的人,但我在之前的问题中找不到答案。我在一个组件中有这个

<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)。
  • 即使 Angular 没有检测到组件输入属性的任何更改(使用 === 检查),它仍然(默认情况下)对所有模板绑定(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/

    10-09 20:54