Angular 移除 ngDestroy 上的 locationStrategyListener

Angular remove locationStrategyListener on ngDestroy

我想知道为什么我的问题看起来如此重要:因为我们已经实现了服务器端查询、分页等。每当用户在 table(例如,当查询 name=x 时,客户端向后端发送带有相应查询参数的请求)。这也意味着我们需要在回溯历史时请求后端,特别是在点击浏览器的后退按钮时。

这适用于以下代码:

constructor(private locationStrategy: LocationStrategy) { }

ngOnInit() {
    this.locationStrategy.onPopState(() => {
        this.refreshHistory();
    })
}

但是,由于在组件的每次初始化中我们都会添加一个新的侦听器来侦听历史事件,因此我们会迅速向后端发送数百个相同的请求(因为每个侦听器都会调用 refreshHistory() 方法) .

我不知何故需要删除ngDestroy接口中的任何eventListener,但locationStrategy似乎没有提供这样的功能。有什么(干净的)方法可以做到这一点吗?

提前致谢!


PS: 如果这是一个完全错误的方法,请纠正我。我更习惯于实现后端而不是前端。

替代方法

我建议您不要使用 LocationStrategy,而是看一下使用路线的 queryParams。您可以在 ngOnInit 中订阅它们,并在 ngOnDestroy 中取消订阅。在您基本上尝试导航回组件中的先前状态的情况下,它似乎会很好用。

例如,用户可能会从此处点击返回:

localhost:4200/#/table?filterString=foo&colSort=idAscending

并在此处结束:

localhost:4200/#/table?filterString=foo

export class MyComponent implements OnInit, OnDestroy {
  paramSub: Subscription;
  constructor(private route: ActivatedRoute) { }

  ngOnInit() {
    this.paramSub = this.route.queryParams.subscribe(params => {
      console.log(params); // query params changed, getData()
    })
  }

  ngOnDestroy(){
    this.paramSub.unsubscribe();
  }
}

除了 angular 文档之外,我发现这篇文章对开始使用 QueryParams 很有帮助 https://alligator.io/angular/query-parameters/

额外

正如您所指出的,LocationStrategy 的问题是没有提供删除侦听器的方法。

我不知道是否可以继续这种方法,但它肯定更复杂。您可以尝试使用命名函数,而不是像这样的匿名函数:

  constructor(private location: LocationStrategy) { }

  ngOnInit() {
    this.location.onPopState(this.popStateHandler);
  }

  popStateHandler(event){
    console.log('handle onPopState', event);
  }

这似乎是朝着正确方向迈出的一步,因为它解决了每次初始化组件时注册新处理程序函数的问题。但随后的问题是,无论您在应用程序中的哪个位置,每次您单击后退时,都会触发处理函数。

一旦阅读了大量的 RxJS 文档,解决这个问题的方法实际上非常简单。 我们使用它的 fromEvent 运算符来创建 onPopState 事件的订阅。从这个订阅中,我们可以轻松取消订阅,一切都很顺利。

import {fromEvent, Subscription} from "rxjs";

export class CommentAllComponent implements OnInit, OnDestroy {

    private backEvent: Subscription;

    ngOnInit() {
        this.backEvent = fromEvent(window, 'popstate').subscribe(() => {
        // doCustomRefresh()
        });
    }

    ngOnDestroy(): void {
        this.backEvent.unsubscribe();
    }
}