区分不同类型的 beforeunload 事件

Posted

技术标签:

【中文标题】区分不同类型的 beforeunload 事件【英文标题】:Distinguish between different types of beforeunload events 【发布时间】:2021-12-10 20:47:31 【问题描述】:

javascript 中,是否可以区分由用户关闭浏览器选项卡和单击 mailto 链接触发的 beforeunload 事件?

基本上,我想这样做:

window.addEventListener("beforeunload", function (e) 

    if(browserTabClosed) 
        // Do one thing
    
    else if (mailtoLinkClicked) 
        // Do a different thing
    

【问题讨论】:

了解您的应用程序为何需要区分您描述的情况可能很有用? 【参考方案1】:

通过查看传入的事件(下面的e)找到了解决方案:

window.addEventListener("beforeunload", function (e) 

    // We can use `e.target.activeElement.nodeName`
    // to check what triggered the passed-in event.
    // - If triggered by closing a browser tab: The value is "BODY"
    // - If triggered by clicking a link: The value is "A"
    const isLinkClicked = (e.target.activeElement.nodeName === "A");

    // If triggered by clicking a link
    if (isLinkClicked) 
        // Do one thing
    
    // If triggered by closing the browser tab
    else 
        // Do a different thing
    

【讨论】:

【参考方案2】:

beforeunload 方法在浏览器之间的行为不稳定,原因是浏览器实现试图避免弹出窗口和其他在此处理程序中运行的恶意代码。

实际上没有通用(跨浏览器)方法来检测触发beforeunload 事件的原因。

说,在您的情况下,您可以检测到点击 window 以区分两种必需的行为:

window.__exit_with_link = false;
window.addEventListener('click', function (e) 
    // user clicked a link
    var isLink = e.target.tagName.toLowerCase() === 'a';

    // check if the link has this page as target:
    // if is targeting a popup/iframe/blank page
    // the beforeunload on this page
    // would not be triggered anyway
    var isSelf = !a.target.target || a.target.target.toLowerCase() === '_self';
    
    if (isLink && isSelf) 
        window.__exit_with_link = true;

        // ensure reset after a little time
        setTimeout(function() window.__exit_with_link = false; , 50);
    
    else  window.__exit_with_link = false; 
);

window.addEventListener('beforeunload', function (e) 
    if (window.__exit_with_link) 
        // the user exited the page by clicking a link
    
    else 
        // the user exited the page for any other reason
    

显然这不是正确的方法,但仍然有效。

同样,您可以添加其他处理程序来检查用户离开页面的其他原因(例如,键盘 CTRL-R 用于刷新等)

【讨论】:

以上是关于区分不同类型的 beforeunload 事件的主要内容,如果未能解决你的问题,请参考以下文章

beforeunload事件

如何在 beforeunload 事件上设置我自己的消息 [重复]

在 beforeunload 事件处理程序中停止页面卸载

js_页面关闭beforeunload事件

html 使用Google Analytics和beforeunload事件跟踪表单放弃

如何在 React 中使用窗口的 beforeunload 事件执行 axios 代码