Heim > Fragen und Antworten > Hauptteil
Meine Bildungserfahrung ist wie folgt:
<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>
und sind die folgenden Komponenten
<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>
Verfügt über die folgende Logik zum Anzeigen von aus Parametern erhaltenen Daten:
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; } }
Ich verwende benutzerdefinierte Ereignisse, um Updates zu verarbeiten
@Output() updatedValue: EventEmitter<any> = new EventEmitter<string>(); constructor() {} ngOnInit(): void {} fieldChanged(changes: SimpleChanges) { this.updatedValue.emit(changes); }
Dann habe ich das folgende HTML zum Bearbeiten der Daten:
<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>
Die aktualisierten Daten im Feld [value]="loadedEducation.school" (updatedValue)="loadedEducation.school = $event"
werden jedoch nicht an die untergeordnete Komponente gebunden, sodass nichts angezeigt wird, bis sie aktualisiert wird und die Daten aus der Datenbank abruft.
Welche Möglichkeiten kann ich versuchen umzusetzen?
Ich habe versucht, ngOnChanges zu implementieren, aber ohne Erfolg.
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
)等