我的教育經驗如下:
<cdk-virtual-scroll-viewport itemSize="5" class="list-scroll"> <app-education-item *ngFor="let education of loadedEducations" (isSelected)="changeSelected(education)" [ngClass]="{ selected: education == loadedEducation }" [education]="education" (isRemoved)="removeEducation(education)" ></app-education-item> </cdk-virtual-scroll-viewport>
並且是以下元件
<div [ngClass]="{ 'list-item-container-collapsed' : isCollapsed, 'list-item-container': !isCollapsed, 'unselected': !isActive, 'selected': isActive}" (click)="selectEducation()"> <div class="top-items-container" style="display: flex;"> <div class="item-text"> <span class="txt-header">{{educationHeader}}</span> <p class="txt-date"> <span>{{startDate}}</span> - <span>{{endDate}}</span> </p> </div> </div>
具有以下邏輯,用於顯示從參數中取得的資料:
export class EducationItemComponent implements OnInit { @Input() education: Education; isCollapsed = false; isActive = false; startDate: string; endDate: string; educationHeader: string; educationDescription: string; constructor() { } ngOnInit(): void { console.log(this.education); this.startDate = this.education.startDate != '' ? formatDate(this.education.startDate, 'MMM yyyy', 'en-US') : formatDate(new Date(), 'MM YYYY', 'en-US') ; this.endDate = this.education.endDate != 'present' ? this.endDate = formatDate(this.education.endDate, 'MMM yyyy', 'en-US') : this.education.endDate; this.educationHeader = this.education.degree == undefined || this.education.description == undefined ? '' : this.education.degree + ' at ' + this.education.school; if (!this.education.description.enUS && this.education.description.nlNL) { this.educationDescription = this.education.description.nlNL; } else if (this.education.description.enUS) { this.educationDescription = this.education.description.enUS; } }
我使用自訂事件來處理更新
@Output() updatedValue: EventEmitter<any> = new EventEmitter<string>(); constructor() {} ngOnInit(): void {} fieldChanged(changes: SimpleChanges) { this.updatedValue.emit(changes); }
然後我有以下 html 用於操作資料:
<div class="update-wrap"> <div class="list-header">Update education</div> <div> <div class="col-sm-6 input-wrapper"> <app-input-field label="Institution" [value]="loadedEducation.school" (updatedValue)="loadedEducation.school = $event" ></app-input-field> </div> <div class="col-sm-6 input-wrapper date-picker-input"> <app-input-field label="Degree" [value]="loadedEducation.degree" (updatedValue)="loadedEducation.degree = $event" ></app-input-field> </div> </div> </div>
但是,欄位[value]="loadedEducation.school" (updatedValue)="loadedEducation.school = $event"
中的更新資料不會與子元件綁定,因此在刷新並取得之前不會顯示任何內容來自資料庫的資料。
我可以嘗試實現哪些可能性?
我嘗試實現 ngOnChanges,但沒有成功。
當您變更清單中項目的屬性時,loadedEducations 清單不會變更。嘗試重新整理清單(
this.loadedEducations = returnedEducations
)或在專案中使用狀態管理問題的根本原因是
@Input()
無法偵測到物件和陣列內部的更改,因為它們都是 引用類型。您的education
屬性是一個對象,因此在父元件中進行的直接改變屬性的變更(例如education.school = 'newValue'
)不會觸發子元件的屬性@Input() education
的任何變更有幾種方法可以解決這個問題,每種方法都有其優點和缺點:
僅傳遞您需要的屬性作為基元
parent.component.ts
parent.component.html
child.component.ts
優點:
缺點:
@Input
數量的增長,變得笨重Education
介面)綁定更改時在父級中重建物件
parent.component.ts
深度克隆
parent.component.html
child.component.ts
優點:
Education
接口,保持父元件和子元件之間的語意耦合缺點:
updateEducation()
函數將反應性元素傳遞到您的子元件中,例如
BehaviorSubject
,並直接訂閱更改parent.component.ts
parent.component.html
child.component.ts
child.component.html
優點:
educationSubject
放入服務中,並將相同的服務注入到任何需要它的元件中缺點:
updateEducation()
函數| async
)等