在@Input()之后,数组是否会更改为对象?

时间:2017-02-04 11:59:28

标签: arrays angular ngonchanges

我对Angular 2很陌生,我希望通过@Input()将父组件中的数组传输给它的子组件。

在父级中,我创建数组,从服务添加数据,并在控制台中显示它(控制台输出1)。在子组件中,我然后使用ngOnChanges再次在控制台中显示它(控制台输出2)。如下所示,数组的长度从12变为0.我想这是因为当数组传递给子进程时,数组会更改为对象?

我该如何解决这个问题?

import { Component, OnInit } from '@angular/core';
import { Module, MapMarkerData } from './coreclasses';
import { TimelineService } from './input.service';

@Component({
  selector: 'my-app',
  templateUrl: 'app/app.component.html',
  providers: [TimelineService]
})

export class AppComponent implements OnInit {
  modules: Module[];
  mapMarkerData: any;

  constructor(private timelineService: TimelineService) {
    this.mapMarkerData = new Array<MapMarkerData>();
  }

  getModules(): void {
    this.timelineService.getModules().then(modules => {this.modules = modules; this.setMapModuleData(this.modules);});
  }

  setMapModuleData(modules: Array<any>): void {
    for (let module of modules) {
      if (module.className) {
        var id = module.id;
        var className = module.className;
        let contents: Object = {id: id, className: className};
        this.mapMarkerData.push(contents);
      }
    }
    console.log(this.mapMarkerData); // CONSOLE OUTPUT 1
    console.log(this.mapMarkerData.length);
  }
}

import { Component, Input, OnInit, OnChanges, SimpleChanges } from '@angular/core';
import { MapMarkerData } from './coreclasses';

@Component({
    selector: 'timeline-map',
    templateUrl: 'app/timeline.map.component.html'
})

export class TimelineMapComponent implements OnChanges {
    @Input()
    mapMarkerData: any;

    ngOnChanges(changes: any) {
      console.log(this.mapMarkerData);  // CONSOLE OUTPUT 2
      console.log(this.mapMarkerData.length);
    }
}

父模板

...
<div id="map" class="mapLarge">
  <timeline-map [mapMarkerData] = "mapMarkerData"></timeline-map>
</div>
...

控制台输出1     数组[12]:[对象,对象,...]

控制台输出2     数组[0]:[对象,对象,...]

1 个答案:

答案 0 :(得分:2)

编辑重要

因为您将相同的引用传递给子组件,所以ngOnChanges生命周期只触发了一次。

请查看此版本,打开控制台标签:https://plnkr.co/edit/WUDGOx?p=preview

所以,如果你想捕捉ngOnChanges生命周期中的每一个变化,你必须传递一个差异数组,如下所示:https://plnkr.co/edit/8awiqe?p=preview

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-root',
  template: `
    <h2>App Component</h2>
    <p><strong>This app will trigger ngOnChanges with immutable array</strong></p>
    <app-content [posts]="posts">
    </app-content>
  `
})
export class AppComponent implements OnInit {
  latestPosts: any[] = [];
  posts: any[] = [];


  ngOnInit() {
    // fake api call
    setTimeout(() => {
      this.latestPosts.push.apply(this.latestPosts, [
        {name: 'Post no.1'}, 
        {name: 'Post no.2'},
        {name: 'Post no.3'}
      ]);
      this.posts = [].concat(this.latestPosts);
    }, 300);
  }

}

===第二个选项=== 您可以自行查看DoCheck生命周期:https://plnkr.co/edit/oxsISD?p=preview

import { Component, Input, DoCheck, IterableDiffers } from '@angular/core';

@Component({
  selector: 'app-content',
  template: `
    Status: {{ status }}
    <div *ngFor="let post of pp">
      {{ post.name }}
    </div>
  `
})

export class ContentComponent implements DoCheck {

  @Input()
  posts: any[];
  differ: IterableDiffers;
  status: string = '';

  constructor(private differs: IterableDiffers) {
        this.differ = this.differs.find([]).create(null);
    }

  ngDoCheck() {
    var changes = this.differ.diff(this.posts);
    if (changes) {
      console.log('ngDoCheck');
      this.status = 'ngDoCheck invoked!'
    }
  }
}

请注意,您必须支付费用,因为上述ngDoCheck方法将在每次更改检测运行时调用。

https://angular.io/docs/ts/latest/guide/lifecycle-hooks.html

https://angular.io/docs/ts/latest/api/core/index/DoCheck-class.html

https://angular.io/docs/ts/latest/api/core/index/SimpleChange-class.html

https://angular.io/docs/ts/latest/api/core/index/IterableDiffers-class.html

<强> END

对于初始状态,它为空,然后该值将分配给此属性。

js log async js log async