Angular+TS:子组件task$是否为父组件数组对象的引用?
问题描述
我正在学习TypeScript与Angular框架。原本计划通过EventEmitter调用更新父组件的数组,目前已实现该功能,但随后发现或许无需这么做——因为我猜测父组件数组与子组件变量是关联的。
我会动态生成子组件,并从父组件的$tasks数组初始化子组件对象。想请教:子组件中的task$对象是否是父组件$tasks数组中对应task对象的引用?
父组件模板
<div *ngIf="task" class="elements"> <app-template-task (ping)="update($event)" [task$]="task" *ngFor="let task of $tasks"></app-template-task> </div>
父组件TypeScript代码
public task: boolean; public taskDone: boolean; public $tasks: Todo[]; public $tasksdone: Todo[]; constructor() { this.task = true; this.taskDone = true; this.$tasks = [ { id: 0, todoText: "Task 1", done: false, position: 1 }, { id: 1, todoText: "Task 2", done: false, position: 2 } ] this.$tasksdone = [] }
子组件模板
<div class="checkbox"> <img *ngIf="task$.done" (click)="changeStatus($event)" src="../../../assets/checked.png" alt=""> <img *ngIf="!task$.done" (click)="changeStatus($event)" src="../../../assets/unchecked.png" alt=""> </div> <div class="text"> <input type="text" [(ngModel)]="task$.todoText" (blur)="changeText($event)" placeholder="Name des Todo punkts"> </div>
子组件TypeScript代码
@Input() task$!: Todo; // ! 允许task理论上可以为null @Output() ping: EventEmitter<any> = new EventEmitter<any>(); constructor() { } public changeStatus(event? : any): void{ this.task$.done = !this.task$.done this.sendEvent("changed") } public changeText(event? : any): void{ console.log(this.task$.todoText) this.sendEvent("textChanged") } private sendEvent(eventIdentifier: string): void{ const eventObject: Eventping = { label: eventIdentifier, object: this.task$ } this.ping.emit(eventObject) }
回答
是的,子组件中的task$对象就是父组件$tasks数组中对应task对象的引用。
原因很明确:在JavaScript/TypeScript中,对象属于引用类型。当你通过Angular的@Input把父组件$tasks数组里的单个Todo对象传递给子组件时,传递的并不是这个对象的副本,而是指向该对象内存地址的引用。这意味着:
- 子组件修改
task$的属性(比如task$.done或task$.todoText)时,会直接修改父组件$tasks数组里的原对象,两者数据完全同步。 - 你当前代码里通过
[(ngModel)]绑定修改todoText、点击切换done状态的操作,已经自动同步到父组件的$tasks数组了,不需要额外通过EventEmitter来更新数组。
需要注意的是:如果子组件直接给task$赋值一个全新的对象(比如this.task$ = { id: 3, todoText: '新任务', done: false }),这时候会切断和父组件原对象的引用关系,新赋值的对象是独立的内存地址,父组件原数组不会被修改。但你当前的代码都是在修改对象属性,所以不存在这个问题。
至于你已经实现的EventEmitter,它并非完全多余:如果父组件需要在子组件修改任务后执行额外逻辑(比如把完成的任务移到$tasksdone数组),EventEmitter可以用来通知父组件触发这些后续操作;但如果只是单纯同步任务属性变化,确实不需要它。
内容的提问来源于stack exchange,提问作者realShao
相关产品推荐
相关产品推荐

