我的教育經驗如下:
<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,但沒有成功。
P粉6589549142024-03-22 14:12:38
當您變更清單中項目的屬性時,loadedEducations 清單不會變更。嘗試重新整理清單(this.loadedEducations = returnedEducations
)或在專案中使用狀態管理
P粉0227236062024-03-22 13:08:51
問題的根本原因是 @Input()
無法偵測到物件和陣列內部的更改,因為它們都是 引用類型。您的education
屬性是一個對象,因此在父元件中進行的直接改變屬性的變更(例如education.school = 'newValue'
)不會觸發子元件的屬性@Input() education
的任何變更
有幾種方法可以解決這個問題,每種方法都有其優點和缺點:
parent.component.ts
education: Education =
parent.component.html
child.component.ts
export class EducationItemComponent implements OnChanges { @Input() school: string; @Input() degree: string; ngOnChanges(changes: SimpleChanges): void { // will emit whenever .school or .degree is changed in the parent } }
優點:
缺點:
@Input
數量的增長,變得笨重Education
介面)綁定parent.component.ts
education: Education =updateEducation(educationProps: Partial ): Education { this.education = { ...this.education, // Note: You may want to 'deep clone' your object depending on how nested it is ...educationProps } }
parent.component.html
child.component.ts
export class EducationItemComponent implements OnChanges { @Input() education: Education; ngOnChanges(changes: SimpleChanges): void { // will emit whenever updateEducation() is called in the parent } }
優點:
Education
接口,保持父元件和子元件之間的語意耦合缺點:
updateEducation()
函數BehaviorSubject
,並直接訂閱更改parent.component.ts
educationSubject: BehaviorSubject= new BehaviorSubject ( ) updateEducation(educationProps: Partial ): Education { const updatedEducation: Education = { ...this.education, // Note: You may want to 'deep clone' your object depending on how nested it is ...educationProps } this.educationSubject.next(updatedEducation} }
parent.component.html
child.component.ts
export class EducationItemComponent implements OnChanges { @Input() educationSubject: BehaviorSubject; }
child.component.html
{{ education.school }}
優點:
educationSubject
放入服務中,並將相同的服務注入到任何需要它的元件中缺點:
updateEducation()
函數| async
)等