在項目中,關于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) | 觸發時機 |
---|---|---|
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.
大致意思:
- 它是個修飾器(一看帶了個@);
- 它需要你傳入兩個參數:
- 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確定,他/她覺得可以這樣做,不然別好心卻被罵了。
以上本文完結。由錯誤的地方或者需要討論的地方請多多指正。