【问题标题】:How to run code after Obsevable AND rendering finished in Angular 11?在 Angular 11 中完成 Observable 和渲染后如何运行代码?
【发布时间】:2021-09-11 00:19:56
【问题描述】:

在我的 Angular 11 项目中,我有一个 Observable,它改变了视图并在渲染时需要一些时间。

类似这样的:

export class MyComponent implements OnInit {
  myObservable = of([1, 2, 3]);

  constructor() { }

  ngOnInit(): void {
    this.myObservable.pipe(
      // here is some functions
    ).subscribe();
  }

}

ngOnInit 运行后,observable 仍在运行和处理数据。数据到达后,管道更改模板。但这种变化发生在ngAfterViewInit 完成之后。所以我需要一个在管道之后运行的灵魂,并且渲染完成了正在发生的事情,因为管道完成了。

如何在我的 observable 和导致的渲染完成后运行代码(工具提示初始化)?

ngAfterViewChecked 不是一个好的解决方案,因为它总是在视图更改时运行,而且我的工具提示初始化也会更改视图。所以我只想运行一次这个初始化。

有什么解决办法吗?

【问题讨论】:

  • 您在每次可观察到的更改后初始化您的工具提示?
  • 在您依赖数据进行预加载的那一刻,您的整个代码将变为异步,因此请使用订阅处理异步数据。如果你想同步它,你可能想Resolve
  • 你看过rxjs的startWith操作符吗?
  • @misha130 是的,因为当它发生变化时,视图也会发生变化,消除以前的工具提示装饰元素,我需要使用新的工具提示参数渲染新元素。
  • @AlekseySolovey 我使用异步数据并使用订阅,但在重新渲染视图后仍然无法运行工具提示初始化。

标签: angular angular-lifecycle-hooks


【解决方案1】:

我找到了解决方法:

我将所有代码放入与工具提示相关的单独组件中。实际上它是一个带有信息图标的label。在这个组件中,我将工具提示初始化代码放入ngAfterViewInit 函数中:

import { AfterViewInit, Component, Input } from '@angular/core';
import { TooltipService } from 'src/app/services/tooltip/tooltip.service';

@Component({
  selector: 'app-wizzard-label',
  templateUrl: './wizzard-label.component.html',
  styleUrls: ['./wizzard-label.component.scss'],
})
export class WizzardLabelComponent implements AfterViewInit {
  @Input() field: any = {};

  constructor(
    private tooltipService: TooltipService,
  ) { }

  ngAfterViewInit(): void {
    this.tooltipService.init();
  }
}

现在当 observable 完成时,让我的微调器消失并显示这个组件。 ngAfterViewInit 做自己的工作,一切正常。

【讨论】:

    【解决方案2】:

    您可以使用 timout 函数作为解决方法,页面将在管道后加载并在一秒钟后执行您的代码,您可以将其减少到不到一秒钟,您可以通过尝试确定它:

    export class MyComponent implements OnInit {
      myObservable = of([1, 2, 3]);
      constructor() { }
    
      ngOnInit(): void {
        this.myObservable.pipe(
          setTimeout( ()=>{
       // your code here
       }, 1000)
        ).subscribe();
      }
    
    }
    

    【讨论】:

    • setTimeout 不是一个好的解决方案,因为我们无法预测这个过程需要多长时间。也许 1 秒太少,也许太多。而且显然没有反应......
    【解决方案3】:

    您可以使用async 管道轻松处理来自 Observables 的数据,如果您需要使用 RxJS pipe 函数,您可以将生成的 Observable 保存到一个新变量中,然后在其上使用 async 管道.

    查看this stackblitz example

    否则,如果管道中的副作用非常复杂,您可以使用 ChangeDetectorRef 手动触发 Angular 更改检测。 查看here 的文档。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-11-25
      • 2017-02-16
      • 2013-05-31
      • 1970-01-01
      • 2012-08-27
      • 1970-01-01
      • 2018-02-20
      • 2016-07-30
      相关资源
      最近更新 更多