Angular点击浏览器的后退/前进按钮更新内容

5

关于问题标题,我已经在Angular 5中编写了一个实现来实现这一点,但是我没有使其工作。

https://stackblitz.com/edit/angular-nhtgbr

想法是每当用户在浏览器中点击后退或前进时,应用程序能够检测到URL更改并更新内容(如果仍在同一组件中)。

import { Component, OnInit } from '@angular/core';
import { Location, PopStateEvent } from '@angular/common';
import { ActivatedRoute, Event, NavigationEnd, Router } from '@angular/router';

@Component({
  selector: 'app-dashboard',
  template: 'Read in console'
})
export class DashboardComponent implements OnInit {

  page: number = 1;

  constructor(private router: Router,
    private activatedRoute: ActivatedRoute,
    private location: Location) { }

  ngOnInit() {

    this.detectPopState();

    setTimeout(() => this.goToPage(1), 1000);
    setTimeout(() => this.goToPage(2), 2000);
    setTimeout(() => this.goToPage(3), 3000);
    setTimeout(() => this.goToPage(4), 4000);
    setTimeout(() => window.history.back(), 5000);  // will trigger location PopStateEvent
    setTimeout(() => window.history.back(), 6000);  // Trigger twice! Expected to trigger only once
    setTimeout(() => window.history.back(), 7000); // Trigger 3 times!
  }

  detectPopState() {
    this.location.subscribe((popStateEvent: PopStateEvent) => {
      // Detect popstate
      if (popStateEvent.type === 'popstate') {
        const eventSubscription = this.router.events.subscribe((event: Event) => {
          if (event instanceof NavigationEnd) {
            this.page = this.activatedRoute.snapshot.queryParams.page;
            this.updateContent();
          }
        });
      }
    });
  }

  updateContent() {
    console.log('Update content ' + this.page);
  }

  goToPage(page: number) {
    this.page = page;
    this.router.navigate(['/dashboard'], {
      queryParams: {
        page: this.page
      }
    });
    this.updateContent();
  }
}

问题在这里:

setTimeout(() => window.history.back(), 6000);  // Trigger twice! Expected to trigger only once
setTimeout(() => window.history.back(), 7000); // Trigger 3 times!

我知道updateContent()由于PopStateEvent的多个订阅而被累计触发,但我仍在努力寻找解决方法以实现我想要的行为。

1个回答

3
因为您没有取消订阅router.events(可观察对象)的订阅。因此,您最终会导致内存泄漏。
解决方案:
取消订阅router.events的订阅。
this.location.subscribe((popStateEvent: PopStateEvent) => {
      if (popStateEvent.type === 'popstate') {
        const eventSubscription = this.router.events.subscribe((event: Event) => {
          if (event instanceof NavigationEnd) {
            this.page = this.activatedRoute.snapshot.queryParams.page;
            this.updateContent();

            // Here it is
            eventSubscription.unsubscribe();

          }
        });
      }
    });

现在它已经完美地运行。您可以从Stackblitz测试。(确保在新窗口中打开输出)


1
我发誓在发布之前已经尝试过你的方法,但是对我来说现在可以工作了! - Kit Loong

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接