是否有任何跨浏览器的JavaScript/jQuery代码来检测浏览器或浏览器标签是否正在关闭,但不是由于链接被单击?


当前回答

如果我没说错,你想知道什么时候一个标签/窗口是有效关闭的。好吧,在JavaScript中检测这个的唯一方法是使用onunload或onbeforeunload事件。

不幸的是(或幸运的是?),当您通过链接或浏览器的后退按钮离开网站时,这些事件也会被触发。这是我能给出的最好答案,我不认为你能在JavaScript中原生检测纯close。如果我说错了,请指正。

其他回答

onunload是Chrome的答案。根据caniuse它的交叉浏览器。但并非所有浏览器的反应都一样。

window.onunload = function(){
    alert("The window is closing now!");
}

developer.mozilla.org

这些事件在窗口卸载其内容和资源时触发。

铬:

Onunload只在页面关闭时执行。它甚至不会在页面刷新和导航到另一个页面时执行。

Firefox v86.0版本:

它根本不会执行。页面刷新,导航离开,关闭浏览器标签,关闭浏览器,什么都没有。

没有事件,但是有一个属性窗口。在撰写本文时,所有主要浏览器都支持关闭。因此,如果您确实需要了解,可以轮询窗口以检查该属性。

如果(myWindow.closed){做事}

注意: 轮询任何东西通常都不是最佳解决方案。窗外。如果可能的话,应该使用Onbeforeunload事件,唯一的警告是,如果您导航离开,它也会触发。

浏览器已经进行了更新,以便在用户离开应用程序时更好地调整用户。事件“visibilitychange”让你在页面从另一个选项卡隐藏或关闭时进行调整。您可以跟踪文档可见性状态。财产文件。visbilitystate将返回当前状态。您将需要跟踪标志的进出,但它更接近目标。

更新的浏览器支持这一点,但safari(正如我们所知)从来不符合标准。你可以使用' pagshow '和'pagehide'在safari中工作。

您甚至可以使用像sendBeacon这样的新API在标签关闭时向服务器发送单向请求,并且不应该期待响应。

我构建了一个类的快速端口,用于跟踪此情况。我不得不删除框架中的一些调用,所以它可能是bug,但这应该让你开始。

export class UserLoginStatus
{
    /**
     * This will add the events and sign the user in.
     */
    constructor()
    {
        this.addEvents();
        this.signIn();
    }

    /**
     * This will check if the browser is safari. 
     * 
     * @returns {bool}
     */
    isSafari()
    {
        if(navigator && /Safari/.test(navigator.userAgent) && /Chrome/.test(navigator.userAgent))
        {
            return (/Google Inc/.test(navigator.vendor) === false);
        }
        return false;
    }

    /**
     * This will setup the events array by browser.
     * 
     * @returns {array}
     */
    setupEvents()
    {
        let events = [
            ['visibilitychange', document, () =>
            {
                if (document.visibilityState === 'visible')
                {
                    this.signIn();
                    return;
                }

                this.signOut();
            }]
        ];

        // we need to setup events for safari
        if(this.isSafari())
        {
            events.push(['pageshow', window, (e) =>
            {
                if(e.persisted === false)
                {
                    this.signIn();
                }
            }]);

            events.push(['pagehide', window, (e) =>
            {
                if(e.persisted === false)
                {
                    this.signOut();
                }
            }]);
        }

        return events;
    }

    /**
     * This will add the events.
     */
    addEvents()
    {
        let events = this.setupEvents();
        if(!events || events.length < 1)
        {
            return;
        }

        for(var i = 0, length = events.length; i < length; i++)
        {
            var event = events[i];
            if(!event)
            {
                continue;
            }

            event[1].addEventListener(event[0], event[3]);
        }
    }

    /**
     * 
     * @param {string} url 
     * @param {string} params 
     */
    async fetch(url, params)
    {
        await fetch(url, 
        {
            method: 'POST',
            body: JSON.stringify(params)
        });
    }

    /**
     * This will sign in the user.
     */
    signIn()
    {
        // user is the app
        const url = '/auth/login';
        let params = 'userId=' + data.userId;

        this.fetch(url, params);
    }

    /**
     * This will sign out the user.
     */
    signOut()
    {
        // user is leaving the app

        const url = '/auth/logout';
        let params = 'userId=' + data.userId;

        if(!('sendBeacon' in window.navigator))
        {
            // normal ajax request here
            this.fetch(url, params);
            return;
        }

        // use a beacon for a more modern request the does not return a response
        navigator.sendBeacon(url, new URLSearchParams(params));
    }
}

简单的解决方案

window.onbeforeunload = function () {
    return "Do you really want to close?";
};

来自MDN文档

由于某些原因,基于webkit的浏览器不符合对话框的规范。一个几乎交叉工作的例子与下面的例子很接近。

window.addEventListener("beforeunload", function (e) {
  var confirmationMessage = "\o/";

  (e || window.event).returnValue = confirmationMessage; //Gecko + IE
  return confirmationMessage;                            //Webkit, Safari, Chrome
});

本例处理所有浏览器。