猿问

Angular2更改检测:ngOnChanges未针对嵌套对象触发

Angular2更改检测:ngOnChanges未针对嵌套对象触发

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

<div class="col-sm-5">
    <laps
        [lapsData]="rawLapsData"
        [selectedTps]="selectedTps"
        (lapsHandler)="lapsHandler($event)">
    </laps></div><map
    [lapsData]="rawLapsData"
    class="col-sm-7"></map>

在控制器中rawLapsdata不时变异。

laps,数据以表格格式输出为HTML。每当rawLapsdata发生变化时,这都

我的map组件需要ngOnChanges用作在Google地图上重绘标记的触发器。问题是当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。当我改变变焦时,我确实看到了标记的变化。所以唯一的问题是我在输入数据发生变化时没有收到通知。

在父母,我有这条线。(回想一下,变化反映在圈数中,但不反映在地图中)。

this.rawLapsData = deletePoints(this.rawLapsData, this.selectedTps);

请注意,this.rawLapsData它本身是指向大型json对象中间的指针

this.rawLapsData = this.main.data.TrainingCenterDatabase.Activities[0].Activity[0].Lap;



慕尼黑8549860
浏览 1911回答 3
3回答

米琪卡哇伊

rawLapsData&nbsp;继续指向同一个数组,即使您修改了数组的内容(例如,添加项目,删除项目,更改项目)。在更改检测期间,当Angular检查组件的输入属性以进行更改时,它(基本上)===使用脏检查。对于数组,这意味着对数组引用(仅)进行脏检查。由于rawLapsData数组引用没有改变,ngOnChanges()因此不会被调用。我可以想到两种可能的解决方案:实现ngDoCheck()并执行您自己的更改检测逻辑,以确定数组内容是否已更改。(Lifecycle Hooks doc有一个例子。)rawLapsData每当您对数组内容进行任何更改时,都会分配一个新数组。然后ngOnChanges()将调用因为数组(引用)将显示为更改。在你的回答中,你提出了另一个解决方案。在OP上重复一些评论:我仍然没有看到如何laps能够接受改变(当然它必须使用与ngOnChanges()自身相当的东西?)而map不能。在laps组件中,您的代码/模板遍历lapsData数组中的每个条目,并显示内容,因此在显示的每个数据上都有Angular绑定。即使Angular没有检测到组件输入属性的任何更改(使用===检查),它仍然(默认情况下)脏检查所有模板绑定。当其中任何一个发生变化时,Angular将更新DOM。这就是你所看到的。该maps组件可能在其模板中没有任何绑定到其lapsData输入属性,对吧?这可以解释不同之处。请注意,lapsData在组件和rawLapsData父组件中都指向相同/一个数组。因此,即使Angular没有注意到对lapsData输入属性的任何(引用)更改,组件“get”/看到任何数组内容更改,因为它们共享/引用该一个数组。我们不需要Angular来传播这些更改,就像我们使用基本类型(字符串,数字,布尔值)一样。但是对于原始类型,对值的任何更改都将始终触发ngOnChanges()- 这是您在答案/解决方案中利用的内容。正如您可能已经想到的那样,对象输入属性与数组输入属性具有相同的行为。

宝慕林4294392

不是最干净的方法,但每次更改值时都可以克隆对象?&nbsp;&nbsp;&nbsp;rawLapsData&nbsp;=&nbsp;Object.assign({},&nbsp;rawLapsData);我想我更喜欢这种方法而不是实现你自己的方法,ngDoCheck()但也许像@GünterZöchbauer这样的人可能会参与其中。

慕斯王

作为Mark Rajcok第二个解决方案的延伸每当对数组内容进行任何更改时,都会为rawLapsData分配一个新数组。然后将调用ngOnChanges(),因为数组(引用)将显示为更改您可以像这样克隆数组的内容:rawLapsData&nbsp;=&nbsp;rawLapsData.slice(0);我提到这个是因为rawLapsData = Object.assign({},rawLapsData);不适合我。我希望这有帮助。
随时随地看视频慕课网APP

相关分类

AngularJS
我要回答