Sudut - Cara mengemas kini komponen kanak-kanak yang mengambil parameter input dan memaparkannya dengan betul pada kali pertama
P粉463418483
P粉463418483 2024-03-21 21:06:55
0
2
442

Pengalaman pendidikan saya adalah seperti berikut:

<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>

dan merupakan komponen berikut

<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>

Mempunyai logik berikut untuk memaparkan data yang diperoleh daripada parameter:

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;
    }
}

Saya menggunakan acara tersuai untuk mengendalikan kemas kini

@Output() updatedValue: EventEmitter<any> = new EventEmitter<string>();

  constructor() {}

  ngOnInit(): void {}

  fieldChanged(changes: SimpleChanges) {
    this.updatedValue.emit(changes);
  }

Kemudian saya mempunyai html berikut untuk memanipulasi data:

<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>

Walau bagaimanapun, data yang dikemas kini dalam medan [value]="loadedEducation.school" (updatedValue)="loadedEducation.school = $event" tidak akan terikat pada komponen anak, jadi tiada apa yang akan dipaparkan sehingga ia menyegarkan dan mendapat data daripada pangkalan data.

Apakah kemungkinan yang boleh saya cuba laksanakan?

Saya cuba melaksanakan ngOnChange tetapi tidak berjaya.

P粉463418483
P粉463418483

membalas semua(2)
P粉658954914

Senarai Pendidikan yang dimuatkan tidak berubah apabila anda menukar sifat item dalam senarai. Cuba muat semula senarai (this.loadedEducations = returnedEducations) atau gunakan pengurusan negeri dalam projek anda

P粉022723606

Punca masalah adalah sebarang perubahan dalam @Input() 无法检测到对象和数组内部的更改,因为它们都是 引用类型。您的 education 属性是一个对象,因此在父组件中进行的直接改变属性的更改(例如 education.school = 'newValue' )不会触发子组件的属性 @Input() education

Terdapat beberapa cara untuk menyelesaikan masalah ini, setiap satu dengan kebaikan dan keburukannya:


Luluskan hanya sifat yang anda perlukan sebagai primitif

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
  }
}

Kelebihan:

  • Mudah dan intuitif untuk digunakan, berfungsi "hanya"
  • Hantar perubahan kepada komponen kanak-kanak tanpa boilerplate tambahan

Kelemahan:

    Boilerplate tambahan diperlukan untuk
  • menerima perubahan kepada komponen kanak-kanak. Apabila bilangan bertambah, ia menjadi sukar digunakan@Input
  • Anda kehilangan gandingan semantik antara komponen ibu bapa dan anak, ia sebenarnya terikat dengan antara muka yang dikongsi (iaitu
  • antara muka) Education
  • Tidak berskala dengan baik jika sifat juga merupakan jenis rujukan, dalam hal ini sifat ini juga perlu dibongkar dan diluluskan sebagai primitif

Bina semula objek dalam induk apabila ditukar

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
  }
}

Klon Dalam

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
  }
}

Kelebihan:

    Kekalkan penggunaan
  • antara muka untuk mengekalkan gandingan semantik antara komponen ibu bapa dan anakEducation
  • Menggalakkan penggunaan
  • objek tidak berubahSecara amnya ia merupakan amalan yang baik untuk objek
  • Tidak memerlukan boilerplate tambahan untuk
  • menerima perubahan kepada subkomponen.

Kelemahan:

    Memerlukan boilerplate tambahan untuk
  • menghantar perubahan kepada komponen anak, iaitu mencipta fungsi berlebihan updateEducation() dalam komponen induk

Salurkan elemen reaktif ke dalam komponen anak anda seperti

dan langgan terus perubahanBehaviorSubject

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 }}

Kelebihan:

  • Kawalan penuh ke atas penghantaran/langganan acara. Ini bagus untuk sebarang kesan sampingan lain yang anda ingin cetuskan
  • Boleh diperluaskan dengan mudah untuk menggunakan banyak komponen, cth. meletakkan educationSubject ke dalam perkhidmatan dan menyuntik perkhidmatan yang sama ke dalam mana-mana komponen yang memerlukannya
  • Juga menyokong penggunaan objek tidak berubah
  • Tiada boilerplate tambahan diperlukan untuk menerima perubahan kepada subkomponen

Kelemahan:

  • Memerlukan boilerplate tambahan untuk menghantar perubahan kepada komponen anak, iaitu mencipta fungsi updateEducation() berlebihan
  • dalam komponen induk
  • Had biasa penggunaan kod reaktif, seperti bermutasi hanya melalui strim, perlu mengelak daripada berhenti melanggan (jika tidak menggunakan | async), dsb.
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan