Angular组件中如何从输入的Contact对象生成数组?
问题:Angular中如何正确将多个Contact类型的props转换为数组?
我定义了一个Contact类:
//Contact.ts export class Contact { name: string; lastName: string; age: number; childrenName: Children[]; constructor(args) { if(args) { Object.assign(this, args) } } }
我的子组件从父组件接收4个Contact类型的props对象:
export class ChildComponent implements onInit { @Input contacts: Contact onInit { console.log(this.contacts) // 对象列表 } }
我原本想把这些Contact对象转换为一个数组,于是在组件里定义了arrayContacts = []属性,然后调用arrayContacts.push(this.contacts)。但结果出问题了:每个Contact对象都被添加到数组的索引0位置,最终数组变成了这样:
0: contacts {name: "John" ...} 0: contacts {name: "Mark" ...} 0: contacts {name: "Ben" ...} 0: contacts {name: "Lilly" ...}
请问正确的实现方式应该是什么?
解答
先给你揪两个小错误:子组件里的生命周期钩子是ngOnInit不是onInit(少了ng前缀),而且@Input要加括号写成@Input()才是正确的语法。
问题根源
你现在的情况大概率是父组件没有一次性传递Contact数组,而是多次单独传递单个Contact对象给子组件。再加上你可能没处理输入属性的动态更新,才会出现所有对象都挤在索引0的问题。
两种正确实现方案
方案1:让父组件直接传递Contact数组(推荐)
这是最合理的做法,直接让子组件接收数组类型的输入,一步到位:
import { OnInit, OnChanges, SimpleChanges } from '@angular/core'; export class ChildComponent implements OnInit, OnChanges { // 把输入类型改成数组,同时初始化空数组避免undefined问题 @Input() contacts: Contact[] = []; arrayContacts: Contact[] = []; ngOnInit() { // 用扩展运算符拷贝数组,避免后续修改影响原输入 this.arrayContacts = [...this.contacts]; console.log(this.arrayContacts); } // 如果父组件会动态更新contacts数组,用ngOnChanges监听变化 ngOnChanges(changes: SimpleChanges) { if (changes['contacts']) { this.arrayContacts = [...changes['contacts'].currentValue]; } } }
父组件模板里直接传数组:
<app-child [contacts]="[contact1, contact2, contact3, contact4]"></app-child>
方案2:适配父组件逐个传递单个Contact的场景(不推荐,但满足需求)
如果父组件确实是每次传一个单独的Contact,你需要监听输入属性的变化,每次收到新对象就添加到数组里:
import { OnInit, OnChanges, SimpleChanges } from '@angular/core'; export class ChildComponent implements OnInit, OnChanges { // 把输入命名改成contact,更符合单个对象的语义 @Input() contact: Contact; arrayContacts: Contact[] = []; ngOnInit() { // 初始化时如果有值就添加 if (this.contact) { this.arrayContacts.push(this.contact); } } // 监听输入属性变化,每次父组件传新对象就追加到数组 ngOnChanges(changes: SimpleChanges) { if (changes['contact'] && changes['contact'].currentValue) { // 可选:避免重复添加同一个对象,根据name判断(你也可以用其他唯一标识) const isDuplicate = this.arrayContacts.some(item => item.name === changes['contact'].currentValue.name); if (!isDuplicate) { this.arrayContacts.push(changes['contact'].currentValue); } } } }
父组件模板如果是循环传递:
<app-child *ngFor="let contact of contactsList" [contact]="contact"></app-child>
额外提醒
- 永远记得初始化数组,避免
undefined.push()的报错 - 如果需要操作数组的独立副本,用扩展运算符
[...]或者Array.from(),不要直接赋值引用 - 输入属性的命名要贴合实际传递的数据类型,避免自己混淆
内容的提问来源于stack exchange,提问作者bernlt
相关产品推荐
相关产品推荐

