【问题标题】:Does array change to an object after @Input() into child?@Input() 变成子元素后数组会变成对象吗?
【发布时间】:2017-06-21 18:14:06
【问题描述】:

我对 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]:[对象,对象,...]

【问题讨论】:

  • 数组在传递给孩子时不会改变。我怀疑Console Output 2 是在Console Output 1 之前打印的。不是这样吗?
  • 更改由changes.mapMarkerData.currentValue访问

标签: arrays angular ngonchanges


【解决方案1】:

编辑重要提示

因为您将相同的引用传递给子组件,所以 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);
  }

}

=== 2nd option ===你可以在DoChecklifecycle: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 日志异步

【讨论】:

  • 感谢您这么快回复!控制台输出 2 不是空的(参见 [Object, Object, ...]),并且包含它从父级接收到的数组的内容,但它的长度不知何故为零。 console.log(changes['mapMarkerData'].currentValue.length) 也给出了 0,但我可以看到它包含数组内容,并且 console.log(changes['mapMarkerData'].previousValue) 应该是空的.那么孩子从其父母那里收到了修改后的数组,但它的显示长度发生了变化?这对我来说真的没有意义吗?
  • 嘿伙计,这是 js 方式,如果你 log 一个数组在时间线 0 为空,然后时间线 1,你给它赋值,它会输出长度 0,但内容不为空
  • 打开控制台选项卡(f12),然后试试这个jsbin.com/perujayewu/edit?js,console,output
  • 我明白了!但是如果我现在想使用这个数组呢?我想循环它的内容,但现在不行。
  • 应该在ngOnInit() life-cycle中执行此操作
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-04-25
  • 1970-01-01
  • 2016-03-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多