单击浏览器后退/前进时的角度更新内容

时间:2018-05-31 11:26:53

标签: angular typescript rxjs angular5 observable

除了问题标题之外,我已经在Angular 5中编写了一个实现来实现这一点但是我没能使它工作。

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

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

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 个答案:

答案 0 :(得分:2)

因为您未取消订阅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();

          }
        });
      }
    });

它现在完美运作。 You can test from Stackblitz。 (确保在新窗口中打开输出)