首页 > 解决方案 > Angular2+/Rxjs Observable 构造函数/ngOnInit - 路由 onPageChange

问题描述

我面临可观察和组件生命周期的问题。这是一个虚拟的stackBlitz:

https://stackblitz.com/edit/angular-ivy-tpytgx

我需要在每个 pageChange 上触发不同组件上的一些特定方法。

  ngOnInit() {
    this.actionsOnRouteChange();
  }

  actionsOnRouteChange() {
    this.router.events.subscribe(event => {
      if (!(event instanceof NavigationEnd) || typeof window === 'undefined') {
        return;
      }
      this.myService.pageChange();
    });
  }
}

最初我有一个这样的代码,但我很挣扎,因为pageChanged$没有取消订阅,所以在根本没有加载组件的页面上也被触发。

  ngOnInit(){
    this.myService.pageChanged$
      .subscribe(() => this.myService.printOnConsole('Hello there!' + this.name))
  }

所以我以这种方式更改了代码。


  subscriptionAlive = true;

  constructor(
    private myService: MyService
  ) {
  }

  ngOnInit(){
    this.myService.pageChanged$
      .pipe(
        takeWhile(() => {
          console.log('alive', this.subscriptionAlive);
        return this.subscriptionAlive})
      )
      .subscribe(() => this.myService.printOnConsole('Hello there!' + this.name))
  }

  ngOnDestroy(){
    this.subscriptionAlive = false;
  }

现在我解决了前面的问题,订阅的回调根本没有被触发,我怀疑这是因为pageChanged$在组件加载之前发出,所以订阅部分还没有初始化。出于这个原因,我以这种方式将订阅移动到构造函数中:

  constructor(
    private myService: MyService
  ) {
    this.myService.pageChanged$
      .pipe(
        takeWhile(() => {
          console.log('alive', this.subscriptionAlive);
        return this.subscriptionAlive})
      )
      .subscribe(() => this.myService.printOnConsole('Secret Info!'))
   }

现在它就像一个魅力,但直到我不需要从他的父级传递组件@Input,我们知道在构造函数中尚未初始化。

在 StackBlitz 中,informationComponent是在没有任何数据传递的情况下工作良好的组件,@InputhelloComponent是需要使用从父组件传递的数据但工作不正常的组件。

我也尝试过ngOnChanges,我也玩过,BehaviorSubject但没有成功。

我错过了什么??

谢谢!

更新 1

我将每个组件的所有订阅都移回ngOnInit并更改Subject<boolean>()BehaviorSubject<boolean>(null),现在它正在工作,但我遇到了另一个问题,我试图在 StackBlitz 上重现但没有成功。在我的真实应用程序中,使用装饰器的组件 (ListMeComponent)@ViewChild似乎调用了发射器两次,如果订阅的代码只在 stackBlitz 中写入,则一次又一次ngOnInitafterViewInitafterViewInit

更新 2

我解决了@ViewChild装饰器设置的问题{ static: true }以便能够使用它ngOnInit,然后我发现它BehaviorSubject被触发了两次,这是他的正常行为,因为如果发射为空,它也会起作用,因为我需要SubjectBehavior解决发射值true并将管道过滤器添加到订阅。

  private pageChanged = new BehaviorSubject<boolean>(null);
  pageChanged$ = this.pageChanged.asObservable();

  pageChange() {
    this.pageChanged.next(true);
    console.log('pageChanged emitted');
  }
    this.myService.pageChanged$
      .pipe(
        takeWhile(() => this.subscriptionAlive),
        filter(isTrue => isTrue)
      )
      .subscribe(() =>
        this.myService.printOnConsoleList(
          'List',
          this.mobileOccasions.nativeElement.offsetParent !== null
        )
      );

我还更新了 stackblitz。

标签: angularrxjsobservableangular2-routing

解决方案


推荐阅读