ホームページ  >  記事  >  ウェブフロントエンド  >  Angular 開発の問題レコード: コンポーネント データをビューにリアルタイムで更新できない

Angular 開発の問題レコード: コンポーネント データをビューにリアルタイムで更新できない

青灯夜游
青灯夜游転載
2022-12-08 20:25:152025ブラウズ

職場で問題が発生しました: Angularコンポーネント データをビューにリアルタイムで更新できません。問題自体は比較的簡単に解決できますが、それでも要約して記録します。

Angular 開発の問題レコード: コンポーネント データをビューにリアルタイムで更新できない

まずは原因について話しましょう。 [関連チュートリアルの推奨事項: "angular チュートリアル"]

問題の原因


##MainComponent:

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

MainComponent があり、このコンポーネント内の別のコンポーネント MenuComponent を参照する必要があります。

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

この

MenuComponent は他のページで使用するのが通常であり、Menu コンポーネントであるため、多くの mouseover イベントが存在します。 、これらのイベントも正常に動作します。ただし、この MenuComponentMainComponent に配置されている場合、mouseover イベントに問題があります。mouseover イベントをデバッグした後、コードは正しく実行されており、コードに問題はないと思います。このコンポーネントは他のページに配置されており、まったく正常に動作するため、コンポーネント自体に問題があるようには思えません。

現象は :

mouseover が非常に奇妙な動作をします。A に移動すると、B のデータが表示されます。 Bに行くとAのデータが表示され、全体がめちゃくちゃになります。

最初の反応は、これは

MainComponentmouseover イベントと競合するのではないかということです。

再度確認しましたが、問題ありませんでした。しかし、予期せぬ利点がありました。ああ、

MainComponent コンポーネントは OnPush 変更検出戦略を使用しています。他のページが正常に動作するのも不思議ではありませんが、ここには問題があります。わかりました。問題は OnPush によって引き起こされているはずです。変更検出戦略については、理解しにくいですが、すでにおなじみになっていますので、この OnPush について簡単に説明しましょう。

OnPush 戦略

Angular には 2 つの変更検出戦略があり、1 つはデフォルト、もう 1 つは OnPush です。 OnPush 変更検出戦略は主にパフォーマンスを向上させることを目的としています。コンポーネント デコレーターの

changeDetection を OnPush に設定すると、Angular は、変更検出がトリガーされるたびに、コンポーネントとコンポーネントのすべてのサブコンポーネントの変更検出 をスキップします。

わかりました。OnPush 変更検出戦略が何であるかもわかりました。これにより、現在のコンポーネントとそのサブコンポーネントの変更検出がスキップされます。つまり、このコンポーネントのプロパティ値を変更した場合、これらのプロパティ値はビューに更新されません。つまり、コンポーネントの配列とビューが矛盾します。これを理解したところで、戻って

MenuComponent を見てみましょう。

MainComponent の変更戦略は OnPush に設定されているため、そのサブコンポーネント、つまり MenuComponent# の変更検出戦略はスキップされます。 ## 変更検出は機能しなくなりました。ただし、メニューを操作するとビューが変化することがわかります。これはどうなっているでしょうか? ほとんどの人は、

OnPush

が何であるかを理解するのに少し時間を費やしたかもしれませんが、完全には理解していませんでした。読む。

OnPush

戦略では、次の状況がコンポーネント変更検出をトリガーします。 現在のコンポーネントまたはサブコンポーネントの 1 つがイベントをトリガーします

OnPush

コンポーネントまたはそのサブコンポーネントの 1 つが、clickmouseovermouseleave などの (DOM/BOM) イベントを起動します。 resizekeydown を実行すると、変更検出がトリガーされます (コンポーネント ツリー内のすべてのコンポーネントに対して)。 OnPush

戦略では、次の操作は変更検出をトリガーしないことに注意してください:

setTimeout()
  • setInterval()
  • Promise.resolve().then()
  • this.http.get( '. ..').subscribe()
  • ##OnPush
  • 戦略にもかかわらず、
DOM/BOM

イベントが引き続きトリガーされることが判明しました。したがって、 MenuComponent のビューは引き続き変更されます。つまり、この変更検出は機能します。しかし、問題はまだ解決されておらず、マウスオーバーするとメニューが混乱したままになります。もう一度コードを見てみましょう。

ngOnInit(): void {
    this.mouseOver$.pipe(debounceTime(250)).subscribe((data) => {
       this.menu = &#39;New: &#39; + this.menu;
    });
}
問題は debounceTime が原因です。以前 Rxjs の原理を紹介したときに、これは非同期であると言いました。これまで習得してきたことがようやく役に立ちました。

总结一下,就是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();
    });
  }

  ...
}

总结


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

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

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

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

以上がAngular 開発の問題レコード: コンポーネント データをビューにリアルタイムで更新できないの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はjuejin.cnで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。