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

30

我希望能够在我的单页应用(Angular项目)中使用路由来检测页面刷新。

是否有其他替代方法?

5个回答

32

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,刷新以查看差异。

点击页面A和页面B,刷新以查看差异。


3
好的!StackBlitz让你的解决方案容易理解了。 - StackOverflowUser
不错,但我会将其实现为一个服务而不是从app.component导入,因为这会在大型应用程序上导致性能问题。 - jcdsr
这个怎么解决?无论你是在新标签页中输入URL还是刷新页面,router.navigated始终为false。而且在stackblitz控制台中,两种情况下它都会写入true。 - char m
谢谢!我明白,但在这里输入URL,即开始一个新的会话和刷新会话是相同的。至少我想知道现有的会话是否被刷新。这不是解决方法。大多数浏览器都可以做到,但我还没有找到适用于Safari的方法。 - char m
检测浏览器刷新,就像标题所说的那样。当用户拥有一个会话,例如myapp:4200/pageX,并按下F5或浏览器的刷新按钮时,就会发生这种情况。然后它应该返回到myapp:4200/pageX并检测现有会话是否已刷新。我的应用程序非常复杂,我需要知道。其他浏览器通过调用performance.getEntriesByType('navigation')来提供此信息。在Safari中,数组为空。 - char m
显示剩余2条评论

23

试试这个:

  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';

我使用了这段代码,前两次它能够正常工作(当用户点击刷新按钮时,我能够执行一些代码),但是突然间就停止工作了(我提到的代码不再被执行),而且我没有做任何更改。那么这是怎么回事呢?我正在使用 Firefox 71.0。 - GB11
我假设你正在使用 import { filter } from 'rxjs/operators' - DeadlyChambers
@DeadlyChambers,是的import { filter } from 'rxjs/operators'; - Ghoul Ahmed
1
这真的有效吗?因为在我的应用程序中,我正在检查“卸载”事件,所以我想知道是否使用Angular路由也可以实现同样的功能。 - Kardon63

5
一个Angular应用是一个单页应用,在单页应用的语境中,整个应用只会被加载一次,数据或屏幕会在用户使用应用时进行刷新。
浏览器刷新相当于关闭应用并重新启动。没有默认的方法可以在你的Angular应用内部响应它。
你可能可以使用 onBeforeUnload() 来模拟某些东西以记录应用被重新加载的情况;然后在你的应用初始化过程中检查该日志,执行一些特殊操作。

2
如果您正在使用sessionStorage,则会话仍然存在,如果您的应用程序正在使用此sessionStorage,则与关闭和启动不同,因为sessionStorage将在重新加载之间保持。它只会在手动清除或窗口(/标签)关闭时才被清除。 - user12207064

3

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

因此,如果 /somepage 是我们想要检测的页面,并且如果浏览器被刷新,当我们进入此页面时,我们设置 navigate 属性 prevPage

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

然后在somepage内部:

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

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

如果您需要在整个网站中使用此功能,则建议采用不同的方法。


1
不是一个理想的解决方案...! - Vikram Sapate
@VikramSapate 为什么这不是一个理想的解决方案?仅仅说这不理想对任何人都没有好处,只会让人们对上面的答案产生质疑而不知道原因。你应该提供建设性的批评,否则就不要说任何话。 - undefined

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');
     }
}

还有一个 main.ts 文件,用于引导 Angular 应用程序。

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

基本上,只要有JavaScript运行一次的地方...

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