在@Input() 变为child 之后数组是否变为object?
Does array change to an object after @Input() into child?
我是 Angular 2 的新手,我想通过 @Input() 将在 parent 组件中创建的数组传输到它的 child。
在 parent 中,我创建了数组,从服务添加数据,并将其显示在控制台中(控制台输出 1)。在 child 组件中,我然后使用 ngOnChanges 再次在控制台中显示它(控制台输出 2)。正如您在下面看到的,数组的长度从 12 变为 0。我想这是因为数组在传递给 child?
时变为 object
我该如何解决这个问题?
Parent
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);
}
}
Child
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);
}
}
Parent 模板
...
<div id="map" class="mapLarge">
<timeline-map [mapMarkerData] = "mapMarkerData"></timeline-map>
</div>
...
控制台输出 1
数组[12]: [Object, Object, ... ]
控制台输出 2
数组[0]: [Object, Object, ... ]
编辑重要
因为您将相同的引用传递给子组件,所以 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 日志异步
我是 Angular 2 的新手,我想通过 @Input() 将在 parent 组件中创建的数组传输到它的 child。
在 parent 中,我创建了数组,从服务添加数据,并将其显示在控制台中(控制台输出 1)。在 child 组件中,我然后使用 ngOnChanges 再次在控制台中显示它(控制台输出 2)。正如您在下面看到的,数组的长度从 12 变为 0。我想这是因为数组在传递给 child?
时变为 object我该如何解决这个问题?
Parent
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);
}
}
Child
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);
}
}
Parent 模板
...
<div id="map" class="mapLarge">
<timeline-map [mapMarkerData] = "mapMarkerData"></timeline-map>
</div>
...
控制台输出 1 数组[12]: [Object, Object, ... ]
控制台输出 2 数组[0]: [Object, Object, ... ]
编辑重要
因为您将相同的引用传递给子组件,所以 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 日志异步