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

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

一,可监听的事件的列表

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

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

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

事件名称 属性(window.x) 触发时机
beforeunload onbeforeunload 顾名思义,当用户卸载文档执行之前触发
unload onunload 当用户卸载文档执行时触发(浏览器关闭)
load onload 页面加载之后立即触发
resize onresize 当浏览器窗口被调整大小时触发

一些使用场景:

  • 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.

大致意思:

  1. 它是个修饰器(一看带了个@);
  2. 它需要你传入两个参数:
    • 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 ?');
  }
}
...

像这样的话,你会发现你的代码确实是执行了,但是页面同样继续执行了刷新,与我们的期望背道而驰。

提示

这个before unload事件我们写的 returnValue = true实际上你可以写any thing,因为他都会弹出一个基于浏览器的提示框,这个东西就不受你的ux掌控了,所以如果选择使用,请首先和你的ux确定,他/她觉得可以这样做,不然别好心却被骂了。

以上本文完结。由错误的地方或者需要讨论的地方请多多指正。

你可能感兴趣的:(Angular 监听浏览器事件(刷新/关闭/...))