[Angular] Using ngOnChanges lifeCycle hook to break object reference
What could be the issue, for example we have two list:
Parent component:
@Component({ selector: 'passenger-dashboard', styleUrls: ['passenger-dashboard.component.scss'], template: ` <div> <passenger-count [items]="passengers"> </passenger-count> <div *ngFor="let passenger of passengers;"> {{ passenger.fullname }} </div> <passenger-detail *ngFor="let passenger of passengers;" [detail]="passenger" (edit)="handleEdit($event)" (remove)="handleRemove($event)"> </passenger-detail> </div> ` }) export class PassengerDashboardComponent implements OnInit { passengers: Passenger[]; constructor() {} ngOnInit() { this.passengers = [{ id: 1, fullname: 'Stephen', checkedIn: true, checkInDate: 1490742000000, children: null }, { id: 2, fullname: 'Rose', checkedIn: false, checkInDate: null, children: [{ name: 'Ted', age: 12 },{ name: 'Chloe', age: 7 }] }, { id: 3, fullname: 'James', checkedIn: true, checkInDate: 1491606000000, children: null }, { id: 4, fullname: 'Louise', checkedIn: true, checkInDate: 1488412800000, children: [{ name: 'Jessica', age: 1 }] }, { id: 5, fullname: 'Tina', checkedIn: false, checkInDate: null, children: null }]; } handleEdit(event: Passenger) { this.passengers = this.passengers.map((passenger: Passenger) => { if (passenger.id === event.id) { passenger = Object.assign({}, passenger, event); } return passenger; }); } handleRemove(event: Passenger) { this.passengers = this.passengers.filter((passenger: Passenger) => { return passenger.id !== event.id; }); } }
Child component:
@Component({ selector: 'passenger-detail', styleUrls: ['passenger-detail.component.scss'], template: ` <div> <span class="status" [class.checked-in]="detail.checkedIn"></span> <div *ngIf="editing"> <input type="text" [value]="detail.fullname" (input)="onNameChange(name.value)" #name> </div> <div *ngIf="!editing"> {{ detail.fullname }} </div> <div class="date"> Check in date: {{ detail.checkInDate ? (detail.checkInDate | date: 'yMMMMd' | uppercase) : 'Not checked in' }} </div> <div class="children"> Children: {{ detail.children?.length || 0 }} </div> <button (click)="toggleEdit()"> {{ editing ? 'Done' : 'Edit' }} </button> <button (click)="onRemove()"> Remove </button> </div> ` }) export class PassengerDetailComponent implements OnInit { @Input() detail: Passenger; @Output() edit: EventEmitter<any> = new EventEmitter(); @Output() remove: EventEmitter<any> = new EventEmitter(); editing: boolean = false; constructor() {} ngOnInit() { console.log('ngOnInit'); } onNameChange(value: string) { this.detail.fullname = value; } toggleEdit() { if (this.editing) { this.edit.emit(this.detail); } this.editing = !this.editing; } onRemove() { this.remove.emit(this.detail); } }
They both display list of "passengers".
What will happens that when we change the "passenger" value in 'passenger-detail' component. It will using '(edit)' event to update parent component's 'passengers' variable.
Both changes happens in the same time.
But what we really want is, until child component click "Done" button then parent component get udpate.
So what we can do is using 'ngOnChanges' in child component to break Javascript object reference (this.detail, which marked in yellow background).
export class PassengerDetailComponent implements OnChanges, OnInit { constructor() {} ngOnChanges(changes) { if (changes.detail) { this.detail = Object.assign({}, changes.detail.currentValue); } console.log('ngOnChanges'); } onNameChange(value: string) { this.detail.fullname = value; } ... }
We use 'Object.assign' to create a new 'this.detail' object reference.
And because of this new creation, it actually breaks the reference of 'this.detail'.
And only when click "Done" button, the deatial will be sent to the parent component.
相关文章
- Angular: 最佳实践
- Angular HTTPClient 发送请求的触发方式讨论
- 关于 Angular HttpClient 的单例特性的思考
- Angular面试题_session面试题
- to program_I Just Want To
- 解决angular创建项目报错:setTimeout is not defined
- 使用 Angular Universal 进行服务器端渲染的防御性编程思路
- Angular 模块封装概念常见的错误理解
- 使用 Angular HTTP_INTERCEPTOR 拦截器来记录超时请求的一些思考
- Angular 项目中 angular.json builder 字段的可选项介绍
- Angular和jQuery的区别
- Angular 2对 React:究竟孰优孰劣?
- Angular用来控制元素的展示与否的原生指令介绍