1

我对 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 Array[0]: [Object, Object, ... ]

4

1 回答 1

2

编辑重要

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

请查看此版本,打开您的控制台选项卡: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

结尾

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

js 异步日志 js 异步日志

于 2017-02-04T12:03:51.670 回答