React組件卸載、路由跳轉、頁面關閉(刷新)以前進行提示

React組件卸載生命週期、路由跳轉和頁面關閉三者看起來有些相似的地方,好比都是當前組件即將從視口消失,但實際上所觸發的事件均不相同。以一個實際案例出發:react

某單頁應用的 文章編輯頁用戶正在編輯文章,此時還沒有保存。

當用戶不當心要跳轉到另一個路由時須要提醒用戶是否繼續跳轉,這個過程須要觸發路由跳轉以及組件卸載api

而用戶不當心點了關閉標籤頁按鈕,或刷新了頁面。這個過程觸發了頁面卸載事件;數組

在這個案例中咱們須要實現:瀏覽器

1. 用戶跳轉頁面時彈出提示框(路由採用histroy模式)網絡

2. 用戶關閉頁面時彈出提示框react-router

componentWillUnmount

首先這個鉤子函數是在組件卸載前調用的一個函數,它並不能阻止當前組件的卸載。因此不要千方百計在這裏作提示,由於即使提示了,組件仍是會卸載,文章仍是會消失。dom

路由守衛-<Prompt/>

爲了實現第一個功能,須要一個跳轉路由以前進行的判斷。在react-router-dom 4.0 以後取消了先前的路由守衛(其實我沒研究過以前版本的,這個描述摘自網絡)。在react-router-dom 4.0以後,實現這個功能能夠依靠<Prompt/>組件。文檔連接↗函數

把這個組件添加到你的文章編輯頁組件的任意部分code

import {Prompt} from 'react-router-dom';
const Editor=()=>{
    return (
        <div>
          <Prompt
            when={true}
            message={location => '文章要保存吼,肯定離開嗎?'}
          />
        </div>
    )
}

這裏有一點須要注意,使用<Prompt/>時,你的路由跳轉必須經過<Link/>實現,而不能依靠<a/>原生標籤。
點擊取消時就會留在當前頁面。至此已經實現了路由跳轉時提醒用戶進行保存的功能。component

窗口關閉事件-beforeunload

實現第二個功能須要依靠對窗口的監聽。React應用中對於窗口事件的應用遠沒有DOM事件頻繁,因此很久沒碰到仍是有點手生的。最關鍵的就是,應該在什麼時候進行監聽?

應該在組件掛載時監聽事件,組件卸載時移除事件監聽。由於我已經開始全面採用hooks新特性了,因此這裏使用到useEffect

import React,{useEffect} from 'react';

const Editor=()=>{

 //監聽窗口事件
    useEffect(() => {
        const listener = ev => {
            ev.preventDefault();
            ev.returnValue='文章要保存吼,肯定離開嗎?';
        };
        window.addEventListener('beforeunload', listener);
        return () => {
            window.removeEventListener('beforeunload', listener)
        }
    }, []);
    
//return ...
}

這裏有幾個須要注意的地方:

  1. useEffect第二個參數爲空數組,表示只調用了componentDidMountcomponentWillUnmount兩個鉤子
  2. 事件監聽和移除的第二個參數爲同一個事件處理函數
  3. beforeunload事件中的confirmpromptalert會被忽略。取而代之的是一個瀏覽器內置的對話框。(參考:MDN|beforeunload
  4. 必需要有returnValue且爲非空字符串,可是在某些瀏覽器中這個值並不會做爲彈窗信息
相關文章
相關標籤/搜索