Rumah > hujung hadapan web > tutorial js > Rekod masalah pembangunan sudut: Data komponen tidak boleh dikemas kini kepada paparan dalam masa nyata

Rekod masalah pembangunan sudut: Data komponen tidak boleh dikemas kini kepada paparan dalam masa nyata

青灯夜游
Lepaskan: 2022-12-08 20:25:15
ke hadapan
2121 orang telah melayarinya

Saya menghadapi masalah di tempat kerja: Sudut data komponen tidak boleh dikemas kini kepada paparan dalam masa nyata Masalah itu sendiri agak mudah untuk diselesaikan, tetapi saya masih meringkaskannya dan merekodkannya.

Rekod masalah pembangunan sudut: Data komponen tidak boleh dikemas kini kepada paparan dalam masa nyata

Mari kita bincangkan puncanya dahulu. [Cadangan tutorial berkaitan: "tutorial sudut"]

Asal usul masalah


MainComponent:

@Component({
  selector: 'main',
  template: `
    <MenuComponent [isReport]="isReport">
	  </MenuComponent>
 `,
  changeDetection:ChangeDetectionStrategy.OnPush
})
export class MainComponent {
  ...
}
Salin selepas log masuk

Kini terdapat MainComponent, dan saya perlu merujuk komponen lain MenuComponent dalam komponen ini.

import { Component, Input} from &#39;@angular/core&#39;;
import { Subject, debounceTime } from &#39;rxjs&#39;;

@Component({
  selector: &#39;movie&#39;,
  styles: [&#39;div {border: 1px solid black}&#39;],
  template: `
    <div (mouseover)="mouseOver()">
      <h3>{{ menu }}</h3>
    </div>`
})
export class MovieComponent {
  @Input() isReport: boolean = false;
  menu: string = &#39;我是Menu&#39;;

  mouseOver$: Subject<any> = new Subject();

  ngOnInit(): void {
    this.mouseOver$.pipe(debounceTime(250)).subscribe((data) => {
       this.menu = &#39;New: &#39; + this.menu;
    });
  }

  mouseOver(): void {
    this.mouseOver$.next(this.menu);
  }
}
Salin selepas log masuk

Ini Komponen Menu adalah perkara biasa untuk digunakan pada halaman lain dan kerana ia merupakan komponen Menu, terdapat banyak acara mouseover , ini juga berfungsi dengan baik. Walau bagaimanapun, MenuComponent ini diletakkan dalam MainComponent, dan terdapat masalah dengan acara mouseover Selepas menyahpepijat acara mouseover, acara kod dilaksanakan dengan betul. Saya rasa tidak ada yang salah dengan kod itu. Oleh kerana komponen ini diletakkan di halaman lain dan berkelakuan seperti biasa, ia tidak merasakan masalahnya adalah dengan komponen itu sendiri. Fenomena yang ditunjukkan oleh

ialah :

alih tetikus dalam Menu berkelakuan sangat pelik Apabila anda pergi ke A, data B dipaparkan . , apabila anda pergi ke B, data A dipaparkan, dan semuanya menjadi kucar-kacir.

Reaksi pertama ialah, bolehkah ini bercanggah dengan acara mouseover dalam MainComponent?

Saya menyemaknya sekali lagi dan mendapati tiada masalah. Tetapi terdapat keuntungan yang tidak dijangka, ah ah, komponen Komponen Utama menggunakan strategi pengesanan perubahan OnPush Tidak hairanlah halaman lain berfungsi dengan baik, tetapi terdapat masalah di sini. Ok, masalah itu sepatutnya disebabkan oleh OnPush. Mengenai strategi pengesanan perubahan, ia tidak mudah untuk anda fahami.

Strategi OnPush

Angular mempunyai dua strategi pengesanan perubahan, satu ialah Lalai dan satu lagi ialah OnPush ini. Strategi pengesanan perubahan OnPush adalah terutamanya untuk meningkatkan prestasi. Apabila kami menetapkan changeDetection penghias komponen kepada OnPush, Angular akan melangkau komponen dan semua pengesanan perubahan subkomponen komponen ini setiap kali pengesanan perubahan dicetuskan.

Baiklah, kami juga tahu apa itu strategi pengesanan perubahan OnPush Ia akan melangkau pengesanan perubahan komponen semasa dan subkomponennya. Dalam erti kata lain, jika anda menukar nilai sifat komponen ini, nilai sifat ini tidak akan dikemas kini kepada paparan, iaitu tatasusunan komponen dan pandangan adalah tidak konsisten. Setelah mengetahui perkara ini, mari kita kembali dan lihat Komponen Menu.

Memandangkan strategi perubahan MainComponent ditetapkan kepada OnPush, strategi pengesanan perubahan subkomponennya akan dilangkau, iaitu MenuComponent pengesanan perubahan tidak berfungsi lagi. Walau bagaimanapun, anda akan mendapati bahawa paparan masih akan berubah apabila anda mengendalikan Menu. Apa yang berlaku?

Kebanyakan orang mungkin telah meluangkan masa seminit untuk memahami apa itu OnPush, tetapi mereka tidak memahaminya secara menyeluruh. Teruskan membaca.

Di bawah strategi OnPush, situasi berikut akan mencetuskan pengesanan perubahan komponen:

Salah satu komponen atau subkomponen semasa mencetuskan peristiwa

Jika komponen OnPush atau salah satu subkomponennya menyalakan peristiwa (DOM/BOM), seperti klik, tetikus, mouseleave , ubah saiz, keydown, kemudian pengesanan perubahan akan dicetuskan (untuk semua komponen dalam pepohon komponen).

Perlu diambil perhatian bahawa dalam strategi OnPush, operasi berikut tidak akan mencetuskan pengesanan perubahan:

  • setTimeout()

  • setInterval()

  • Janji.resolve().then()

  • this.http.get( '. ..').subscribe()

Ternyata walaupun strategi OnPush, acara DOM/BOM akan tetap pengesanan perubahan pencetus , jadi paparan MenuComponent masih akan berubah, iaitu pengesanan perubahan ini berfungsi. Tetapi masalahnya masih tidak selesai, Menu masih akan keliru apabila mouseover! Mari lihat kod itu sekali lagi.

ngOnInit(): void {
    this.mouseOver$.pipe(debounceTime(250)).subscribe((data) => {
       this.menu = &#39;New: &#39; + this.menu;
    });
}
Salin selepas log masuk

Masalahnya disebabkan oleh debounceTime Apabila saya memperkenalkan prinsip Rxjs sebelum ini, saya mengatakan bahawa ini adalah tak segerak. Apa yang saya kuasai sebelum ini akhirnya berguna.

总结一下,就是mouseover是异步的,会触发变更检测,但是由于debounceTime是异步又嵌套了一下,debounceTime一般是用setTimeout来实现的。所以,debounceTime里的数据变化并不能及时的显示到视图中。终于找到问题的根源了。啦啦啦。问题找到了,那解决起来多easy啊。它不是不会触发变更检测吗,我就手动让它触发一下吧。

import { Component, Input, ChangeDetectorRef } from &#39;@angular/core&#39;;
import { Subject, debounceTime } from &#39;rxjs&#39;;

@Component({
  selector: &#39;movie&#39;,
  styles: [&#39;div {border: 1px solid black}&#39;],
  template: `...`
})
export class MovieComponent {
  ...

  constructor(private cd: ChangeDetectorRef){}

  ngOnInit(): void {
    this.mouseOver$.pipe(debounceTime(250)).subscribe((data) => {
       this.menu = &#39;New: &#39; + this.menu;

       this.cd.detectChanges();
    });
  }

  ...
}
Salin selepas log masuk

总结


  • 平时多注意知识积累,不能按照网上说的解决方案复制过来就解决了,遇到简单问题这样是没有问题的,遇到复杂的就没办法了;

  • 当设置为Onpush策略时,要更加注意,用OnPush就是要减少变更检测的次数,就不要无论什么情况都detectChanges,或markForCheck,失去了意义,还是要规范使用;

  • 要优雅实现代码,项目中居然还看到把父组件的ChangeDetectorRef作为输入属性传到子组件中,一看就不懂变更检测啊;

更多编程相关知识,请访问:编程教学!!

Atas ialah kandungan terperinci Rekod masalah pembangunan sudut: Data komponen tidak boleh dikemas kini kepada paparan dalam masa nyata. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Label berkaitan:
sumber:juejin.cn
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan