【问题标题】:How can I detect when the user is leaving my site, not just going to a different page?如何检测用户何时离开我的网站,而不仅仅是转到不同的页面?
【发布时间】:2011-08-23 14:06:30
【问题描述】:

我有一个 onbeforeunload 处理程序

window.onbeforeunload = unloadMess;
function unloadMess(){
  var conf = confirm("Wait! Before you go, please share your stories or experiences on the message forum.");
    if(conf){
    window.location.href = "http://www.domain.com/message-forum";
    }
}

但我不确定如何知道他们在页面上单击的 url 是否在站点内。

我只是希望他们在离开网站时提醒他们。

【问题讨论】:

  • 请不要这样做 - 他们知道他们要离开网站 - 他们点击了链接。这种事情让 javascript 名声不好。
  • 不好。糟糕的开发人员。不要让我用报纸拍你的鼻子。
  • 我不同意关闭投票;可能无需从事件中读取目标,这是另一个问题的意义所在。
  • 只有当用户输入内容时才可以接受,否则当他们离开时这些内容会丢失。例如。 Gmail 撰写电子邮件对话框。更好的解决方案是使用 $(window).unload(..) 并将所有内容保存在 localStorage 中。或者每隔 n 秒保存到 localStorage,例如。比如 Gmail 保存草稿。

标签: javascript jquery


【解决方案1】:

不可能 100% 可靠地做到这一点,但如果您检测到用户何时点击了您网页上的链接,则可以将其用作大部分正确的信号。像这样的:

window.localLinkClicked = false;

$("a").live("click", function() {
    var url = $(this).attr("href");

    // check if the link is relative or to your domain
    if (! /^https?:\/\/./.test(url) || /https?:\/\/yourdomain\.com/.test(url)) {
        window.localLinkClicked = true;
    }
});

window.onbeforeunload = function() {
    if (window.localLinkClicked) {
        // do stuff
    } else {
        // don't
    }
}

【讨论】:

  • 非常不错且不显眼的解决方案
  • 不太可靠。 Micromax 原生浏览器上的 Buggy。可能会给访问者带来非常糟糕的体验。
【解决方案2】:

我有一个想法,但我不知道它是否有效。我的建议是,为每个链接添加一个带有函数调用的 onClick 事件。该函数仅读取 href 属性并存储到具有全局范围的变量中。

var clickedHrefAttrValue = "";
function getClickUrl(currentLink)
{
   clickedHrefAttrValue = $(currentLink).attr("href");
   return true;
}

a 标签的 html 必须如下所示:

<a href="<url>" onClick="getClickUrl(this)">Linktext</a>

在你给定的函数中:

function getClickUrl()
{
   if (clickedHrefAttrValue.indexOf("<your condition>" > -1)
   {
     //what ever you want do to
   }
}

这只是一个想法,但我认为值得一试。

【讨论】:

    【解决方案3】:

    如果您的网站可能同时具有绝对和相对本地链接而遇到问题,我有另一个解决方案(使用 jQuery):

    Demo

    /* EXTERNAL LINK WARNING
    =========================================*/
    $('a').on('click', function(e){
        e.preventDefault();
        var url = $(this).attr('href'),
            host = location.host;       
        if (url.indexOf(host) > -1 || url.indexOf('http','https') == -1){
            /* If we find the host name within the URL,
                   OR if we do not find http or https, 
                   meaning it is a relative internal link
                */
            window.location.href = url;
        } else {
            var warn = confirm('You\'re leaving the domain.\n\nAre you sure?');
            if(warn == true) {
                window.location.href = url,'_blank';
            } else {
                e.preventDefault;
            }
        }
    });
    

    【讨论】:

      【解决方案4】:

      所以我需要这样做,以便如果用户从任何页面离开站点,我可以将其注销,但如果他们在站点内导航,则不能。这是我使用 JS 和 PHP 的解决方案

      在他们需要保持登录状态的每个页面上,设置一个会话变量:

      <?php
          session_start();
          $_SESSION["isInSession"] = true;
      ?>
      

      现在创建两个脚本:

      clear-in-session.php

      <?php
          session_start();
          unset($_SESSION["isInSession"]);
      ?>
      

      logout.php

      <?php
          session_start();
          if(isset($_SESSION["isInSession"]) exit();
          //do logout code here
      ?>
      

      现在我们在 JS 中设置 2 个事件:

      window.addEventListener('beforeunload', function(event) {
          $.ajax({
              type: 'POST',
              async: false,
              url: 'clear-in-session.php'
          });
      });
      window.addEventListener('unload', function(event) {
          $.ajax({
              type: 'POST',
              async: false,
              url: 'logout.php'
          });
      });
      

      解释用户导航到同一站点的另一个页面时的事件顺序:

      1. 用户离开
      2. beforeunload 被触发,调用 clear-in-session.php 删除 isInSession 变量
      3. 新页面已加载,将 isInSession 设置为 true
      4. unload被触发,调用logout.php,但是因为isInSession已经被设置回true,所以永远不会调用注销代码

      当用户导航到站点外部的页面(或站点上未设置 isInSession 的任何页面)时:

      1. 用户离开
      2. beforeunload 被触发,调用 clear-in-session.php 删除 isInSession 变量
      3. 新页面已加载
      4. unload被触发,调用logout.phpisInSession已经被删除,所以调用注销代码

      抱歉,necro 但在搜索此问题的答案时仍会出现此线程

      注意:此答案使用 jQuery 对 php.ini 进行 post 调用。在纯 JS 中完全可以做到这一点,但在 jQuery 中更容易说明

      【讨论】:

        【解决方案5】:

        我最近在我的网站上实施了一个很好的解决方案。想象一下,在您的网站中导航用户的所有内容要么是链接(锚标签)、按钮、可点击的图像,要么是这些行上的东西。它绝对不会是 body 元素。

        现在当用户离开网站时会发生什么,他/她可以输入网址并按回车键、单击书签或按后退/前进按钮。

        当用户这样做时,这样做:

        $(window).on('beforeunload', function(e)){
            if(e.target.activeElement.nodeName.toLowerCase() == 'body'){
               yourFunction();
        });
        

        在这些情况下(当用户离开网站时),主体成为目标中的活动元素,而当用户点击内部网站可导航元素时,情况并非如此。

        这是一个干净、简单的解决方案。如果您遇到任何问题,请告诉我。

        【讨论】:

        • 即使我在我的应用程序/网站(相同的主机/域)url 中,也会调用这个 beforeunload 处理程序并按回车键也被调用?只有当用户输入的主机/网址与我的应用程序不同时,这种方式是否应该调用?
        猜你喜欢
        • 2018-04-06
        • 2015-01-10
        • 1970-01-01
        • 1970-01-01
        • 2019-05-14
        • 1970-01-01
        • 2021-07-09
        • 2018-11-28
        • 1970-01-01
        相关资源
        最近更新 更多