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

...
@HostListener('window:beforeunload', ['$event'])
private beforeUnload(event: Event) {
  if(this.form.dirty) {
    event.preventDefault();
    event.returnValue = true;  // Chrome requires returnValue to be set.
  }
}
....

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

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

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

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

提示

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

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  •   JavaScript 与 HTML 之间的交互是通过事件实现的。   事件,就是文档或浏览器窗口中发生的一些特...
    霜天晓阅读 3,543评论 1 11
  • 本节介绍各种常见的浏览器事件。 鼠标事件 鼠标事件指与鼠标相关的事件,主要有以下一些。 click 事件,dblc...
    许先生__阅读 2,513评论 0 4
  • 之前写过一篇浏览器事件的相关操作和事件运行的原理——JavaScript浏览器事件解析。这一篇主要写一些常用的事件...
    faremax阅读 1,663评论 0 0
  • 资源事件 beforeunload 事件 beforeunload事件在窗口、文档、各种资源将要卸载前触发。它可以...
    oWSQo阅读 638评论 0 1
  • JavaScript 与 HTML 之间的交互是通过事件实现的。事件,就是文档或浏览器窗口中发生的一些特定的交互瞬...
    LemonnYan阅读 699评论 0 4