新新新手阅读 Angular 文件 - Component - ngOnDestroy(2) - Day26

本文内容

接续昨天 ngOnDestroy 还没有记录完的内容。

ngOnDestroy 可能没被启动的状况

这边有一个蛮特别的事情,就是 ngOnDestroy 只会在该元件所处的网页还在运行的状态下才会被启动。
你可能会觉得没什麽特别的,阿不就网页关掉就关掉,还管它什麽元件的 ngOnDestroy 启不启动。
你这样想也是没错,
但...... 如果,我们有在该元件的 ngOnDestroy 写入一些特制的功能(比如: 当该元件进入 ngOnDestroy 时,要直接帮使用者登出的功能),结果使用者直接关掉当下页面,就会导致元件根本就没有进入 ngOnDestroy 的 lifecycle,最终,就会导致我们在 ngOnDestroy 撰写的这些特制的功能没有被启动。
那有哪些状况有可能会造成以上的状况发生呢?

  1. 页面重新整理
  2. 分页被关掉
  3. 整个浏览器被关掉
  4. 使用者直接从当下页面外连到其他页面

HostListener - 监听 DOM 事件

为了解决以上的状况,我们必须要引入 Angular 的 HostListener 来监听网页的 beforeunload 事件。
首先,什麽是 beforeunload 事件呢?
它是一个当网页即将要被关闭或重新整理之前,会被触发的一个事件,当这个事件被触发的时候,网页上的资料都还是被保留状况,也就是使用者还可以反悔的状况。

接着,我们就用 HostListener 来监听 beforeunload 被触发的时候,来执行该元件的 ngOnDestroy 事件,来解决以上的状况。
我们改写一下 Day25 的范例
[子元件 -TypeScript]

import { Component, OnDestroy, HostListener} from '@angular/core';
import { AuthService } from '@app/auth.service.ts'
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';

export class AppComponent implements OnDestroy  {
  // ...
  @HostListener('window:beforeunload')
  ngOnDestroy() {
    this.destroy$.next(true)
    this.destroy$.unsubscribe()
    
    // ... 使用者登出功能,或是其他特制的功能
  }
}

是不是很简单呢~ 只要利用 HostListener 去监听 window:beforeunload 的事件,在这行程序码的下面要接,想要触发的内容,而以上的范例,我们想要接着触发的内容就是 ngOnDestroy 罗。

其实,HostListener 有两个参数,一个是像上面范例所示被监听的 DOM 事件,第二个参数是这个 DOM 事件的内容,
写法如下
@HostListener('window:beforeunload', ['$event'])
你可能会纳闷,为什麽上面的范例你不这样写呢?
原因是,ngOnDestroy 是没有办法传入任何参数的喔,如果,我硬将 $event 写入 ngOnDestroy 的参数部分,会得到以下的错误讯息
https://ithelp.ithome.com.tw/upload/images/20210926/201400930Fo9G7WLAt.png
大概的意思就是无法传入参数给 ngOnDestroy 。

尝试阻止使用者离开当下页面 - 自订义函式

如果,我们今天希望当使用者离开或重整当下页面的时候,会跳出一个 alert 提示使用者是否要离开页面,这个时候,我们可以使用自订义的函式
写法如下
[子元件 -TypeScript]

import { Component, OnDestroy, HostListener} from '@angular/core';
import { AuthService } from '@app/auth.service.ts'
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';

export class AppComponent implements OnDestroy  {
  ngOnDestroy() {
    this.destroy$.next(true)
    this.destroy$.unsubscribe()
  }
  
  @HostListener('window:beforeunload', [$event])
  onBeforeUnload($event) {
    $event.preventDeafult()
    $event.returnValue = true
  }
}

可以看到我们将 HostListener 的部分改写在 onBeforeUnload 的上面,而且传入了 $event ,让我们可以在 onBeforeUnload 里面操作里面的内容。
加入以上的内容之後,当使用者重整或关闭当下页面都会跳出提示讯息,告知使用者即将要离开页面了。

但是,要特别注意的是,当我们改以上面的写法时,该元件的 ngOnDestroy 内容是不会被触发的喔,因为,beforeunload 被触发的当下,你的元件都还是可视的(visible),根本还没有被消除,所以,不会进到 ngOnDestroy 里面。

Summary

来做个总结

  1. 要注意在某些情况下的操作是不会触发元件的 ngonDestroy 的 lifecycle hook 的,这个时候,我们可以利用 HostListener 来监听 window 的 beforeunload 事件,来防止这种事情。
  2. 可以使用 onBeforeUnload 来跳出提示讯息,提醒使用者他即将要离开页面了。

Reference:

  1. Angular HostListener API Doc
  2. Introduce about beforeunload DOM event
  3. Introduce about how to prevent component from not proceeding its ngOnDestroy lifecycle hook when user directly closing brower

<<:  Day 11 Flask 快速开始

>>:  API

[Day13] swift & kotlin 实作篇!(4) 图片资源

swift 首先我们来看看图片资源设定 撰写app的过程中 图片档案要非常小心 不要侵犯到别人的智慧...

[Day 12] 当冲实验结果概述

一、总结 总结来说,今天研究了一整天论文, 该篇论文对蒐集5分线数据,并以此预测之後的股价倾向, 与...

Day 13 - Add Binary

大家好,我是毛毛。ヾ(´∀ ˋ)ノ 废话不多说开始今天的解题Day~ 67. Add Binary ...

基本操作 - 历史资讯

根据官方说明,因为历史资料的查询蛮耗资源的,有可能会拖慢系统的速度,所以官方不建议使用,而且有每5秒...

Day 24-Unit Test 应用於 ORM (以 Entity Framework 为例) (情境及应用-4)

Unit Test 应用於 ORM (以 Entity Framework 为例) - LINQ 介...