Angular 监听浏览器事件(刷新/关闭/...)

在项目中,关于Angular路由跳转的控制(Guard)如果基本都是基于 CanActivatee canDeactivate ,我在文章 Angular的守门员canActivate与canDeactivate 有较为详细的介绍,但是最后也提到,对于浏览器的刷新和关闭, canDeactivate 并不能处理,所以还是得回归本质,直接监听浏览器事件。

一,可监听的事件的列表

学过御三家 Html , css , js 的人应该有耳闻 W3School ,这个强大的网站同样也列出了

我们在开发过程中可能需要监听的事件列表([链接][ https://www.w3school.com.cn/tags/html_ref_eventattributes.asp] )。

本文的目的是监听浏览器事件,但因为浏览器的刷新和关闭会直接触发 Window 事件,所以实际上我们监听的是 Html 中的 Window 事件。这里就只简单列出比较常用的几个事件:

属性(window.x)
  • unload: 可以类比 onDestroy(),我们可以在里面写一些清空临时数据之类的操作;
  • load:可以类比onInit(),可以执行一些初始化的函数在里面;
  • resize:可以直接想到的就是界面大小变化后界面动态适配;
  • beforeunload:这个可以想像成 before ngOnDestroy(),就是还没Destroy之前的操作,这也是经常用到一个事件。
  • 二,@HostListener

    我们在上面我的一篇文章写到一个场景,就是用户在编辑还未保存的情况下离开当前界面,我们需要给他个提醒,当时我们用 canDeactivate 已经解决了大部分场景,但是针对浏览器刷新和关闭不能处理,所以来看看 Angular 中的 Dom Event Listner @HostListener

    官方的解释是:

    Decorator that declares a DOM event to listen for, and provides a handler method to run when that event occurs.
    

    大致意思:

  • 它是个修饰器(一看带了个@);
  • 它需要你传入两个参数:
  • eventName: string // 监听的事件名称
  • args: string[] // 事件发生时传给处理器的参数
  • 注意,我们要传的是事件名称,不是属性,比如你要监听unload,就应该写:

    @HostListener('window:unload', [`$event`]) ...  // right !
    @HostListener('window.onunload', [`$event`]) ...  // wrong !
    @HostListener('window:onunload', [`$event`]) ...  // wrong !
    

    还是那个场景,未保存修改刷新/关闭浏览器,弹出提示:

    import { 
        HostListener,
    } from '@angular/core';
    @HostListern('window: beforeunload', ['$event'])
    private beforeUnload(event: Event) {
      if(this.form.dirty) {
        event.returnValue = true;  // Most important
    

    来看一下代码,我已经标注了非常重要的一步,我们必须对该 event-unload来返回一个值,以此来暂停事件的继续进行(become unload)来达到我们所预期的目的。

    如果不写这一句,直接写你的代码逻辑:

    private beforeUnload(event: Event) { if(this.form.dirty) { // event.returnValue = true; return this.alertService.alert('Are you confrimed ?');