在 Angular 项目中检测浏览器刷新

问题描述 投票:0回答:7

我想在我的单页面应用程序(Angular 项目)中使用路由器来检测页面何时刷新。

还有其他方法吗?

angular routes refresh
7个回答
34
投票

component.ts 文件中:

import { Subscription } from 'rxjs';

export let browserRefresh = false;

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})

export class AppComponent implements OnDestroy {

  subscription: Subscription;

  constructor(private router: Router) {
    this.subscription = router.events.subscribe((event) => {
        if (event instanceof NavigationStart) {
          browserRefresh = !router.navigated;
        }
    });
  }

在您需要的页面中:

import { browserRefresh } from '../app.component';

....

  ngOnInit() {
    this.browserRefresh = browserRefresh;
    console.log('refreshed?:', browserRefresh);
  }

请参阅工作示例:https://stackblitz.com/edit/refreshangular?file=src%2Fapp%2Fpage-a%2Fpage-a.component.ts

点击A页和B页,刷新看看区别。

Click on page A and Page B. Refresh to see the difference2


25
投票

试试这个:

  this.router.events
    .pipe(filter((rs): rs is NavigationEnd => rs instanceof NavigationEnd))
    .subscribe(event => {
      if (
        event.id === 1 &&
        event.url === event.urlAfterRedirects
      ) {
          // Your code here for when the page is refreshd
      }
    })

您需要导入

import { filter } from 'rxjs/operators'
import { Router  } from '@angular/router';

5
投票

Angular 应用程序是单页应用程序,在单页应用程序的上下文中,完整的应用程序加载一次,并且当用户使用您的应用程序时刷新数据或屏幕。

浏览器刷新相当于关闭应用程序并再次启动。在 Angular 应用程序中没有任何默认方式可以对此做出响应。

您也许可以使用 onBeforeUnload() 来模拟某些内容,以记录应用程序已重新加载;然后检查应用程序初始化例程中的日志以执行一些特殊操作。


3
投票

Angular 7 及更高版本中的最新方法是我们现在可以添加路线导航属性。

因此,如果

/somepage
是我们要检测的页面,并且浏览器已刷新,则当我们转到此页面时,我们设置 navigate 属性 prevPage

this.router.navigate(['/somepage'], { state: { prevPage: this.router.url } });

然后在某个页面里面:

ngOnInit(): void {
    const previousUrl = history.state.prevPage ?? null;
    if (!this.previousUrl) {
      console.log('page was refreshed!');
    } else {
      console.log('I came here from: ', previousUrl);
    }
}

注意: 如果您想检测特定页面的浏览器刷新,则此方法有效。

如果您在整个网站上都需要这个,那么我会采用不同的方法。


2
投票

我想使用路由器检测页面何时刷新

您向路由器添加一个顶级解析器。如果您有一个顶级路由器,那么它只会被解析一次,并且子级将处理页面导航。解析器每解析一次就等于浏览器刷新一次页面。

const routes: Routes = [
  {
    path: '',
    component: TopComponent,
    resolve: { loaded: PageLoadedResolver },
    children: [
         ...
    ]
  }
];

还有许多其他方法可以在 Angular 中检测页面加载事件。

你的

AppModule
的构造函数。

@NgModule({...})
export class AppModule {
     public constructor() {
          console.log('page loaded');
     }
}

注入根的服务至少使用一次。

@Injector({provideIn: 'root'})
export class MyService {
     public constructor() {
          console.log('page loaded');
     }
}

还有引导 Angular 应用程序的

main.ts
文件。

    platformBrowserDynamic().bootstrapModule(AppModule)
        .then(() => console.log('page loaded'))
        .catch(err => console.error(err));

基本上,任何有 JavaScript 运行一次的地方......


1
投票

我通常通过检查两个特定的路由器事件来检测页面重新加载。每次浏览器的路径发生变化时,Angular 路由器事件都会从 NavigationStart 开始触发,但是,当页面简单地重新加载时,只会触发结束事件,并且它们从 ActivationEnd 开始触发。

为了能够判断页面是否已重新加载,或者用户是否只是导航到应用程序中的同一位置,我将使用以下代码:

import { Component, inject } from "@angular/core";
import { ActivationEnd, NavigationStart, Router } from "@angular/router";
import { filter, fromEvent, tap } from "rxjs";

@Component({
  selector: 'app-layout',
  templateUrl: './layout.component.html'
})
export class LayoutComponent {
  /* DEPENDENCIES */
  private readonly _router = inject(Router);

  /* MEMBERS */
  constructor() {
    let pageReloaded: {
      started ? : boolean,
      ended ? : boolean
    } = {};

    this._router.events.pipe(
      filter(evt => evt instanceof NavigationStart || evt instanceof ActivationEnd),
      tap(evt => {
        if (evt instanceof NavigationStart) pageReloaded.started = true;
        else pageReloaded.ended = true;
      })
    ).subscribe(evt => {
      if (pageReloaded.started && pageReloaded.ended) console.log('this is a navigation');
      else console.log('this is a page reload');
    });
  }
}

从顶部组件执行此操作很重要,就我而言,我总是从 AppComponent 执行此操作。

注意:这仅检测页面的加载是由导航还是重新加载触发的,它不会干扰这两种情况中的任何一种情况

如果您想要在页面重新加载之前执行某些操作,我建议使用 before unload 事件。我不知道在 Angular 中有任何本地方法可以做到这一点。

我希望有一天这可以帮助别人!


0
投票

刷新触发Scroll事件对象。

class Scroll { type: EventType.Scroll; routerEvent: NavigationEnd | NavigationSkipped;position: [...];anchor: string | null;toString(): string;}

我使用这个对象来获取NavigationEnd事件:

    this.router.events
  .pipe(
    map((event) => (event instanceof Scroll ? event.routerEvent : event)),
    filter((event) => event instanceof ActivationStart || event instanceof NavigationEnd),
    takeUntil(this.destroy$)
  )
© www.soinside.com 2019 - 2024. All rights reserved.