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


当前回答

浏览器已经进行了更新,以便在用户离开应用程序时更好地调整用户。事件“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() {
  console.log('event');
  return false; //here also can be string, that will be shown to the user
}
window.addEventListener("beforeunload", function (e) {
 var confirmationMessage = "tab close";

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

它可以用来提醒用户是否有数据未保存或类似的事情。当标签页关闭或浏览器关闭或网页刷新时,此方法有效。

除非用户没有与网页进行交互,否则它不会工作,这是一种对抗恶意网站.....的机制除非你至少在网站窗口上点击或触摸,否则不会弹出窗口。

<!DOCTYPE html>
<html>
<head>
</head>
<body>
    <form>
        <textarea placeholder = "Write...."></textarea>
    </form>
    <script type="text/javascript">
        window.addEventListener('beforeunload', function (e) {
            e.returnValue = '';
        });
    </script>
</body>
</html>

浏览器已经进行了更新,以便在用户离开应用程序时更好地调整用户。事件“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));
    }
}
//Detect Browser or Tab Close Events
$(window).on('beforeunload',function(e) {
  e = e || window.event;
  var localStorageTime = localStorage.getItem('storagetime')
  if(localStorageTime!=null && localStorageTime!=undefined){
    var currentTime = new Date().getTime(),
        timeDifference = currentTime - localStorageTime;

    if(timeDifference<25){//Browser Closed
       localStorage.removeItem('storagetime');
    }else{//Browser Tab Closed
       localStorage.setItem('storagetime',new Date().getTime());
    }

  }else{
    localStorage.setItem('storagetime',new Date().getTime());
  }
});

JSFiddle Link

嗨,大家好,我能够通过使用浏览器本地存储和时间戳实现“检测浏览器和选项卡关闭事件”点击。希望你们所有的问题都能通过这个解决方案得到解决。

在我最初的研究之后,我发现当我们关闭浏览器时,浏览器会一个接一个地关闭所有的选项卡来完全关闭浏览器。因此,我观察到关闭制表符之间的时间延迟非常小。所以我把这个时间延迟作为我的主要验证点,并能够实现浏览器和选项卡关闭事件检测。

我在Chrome浏览器版本76.0.3809.132上测试了它,发现可以工作

:)如果你觉得我的回答有帮助,请投票....