none
关于 onbeforeunload 的应用 RRS feed

  • 问题

  • 我是想通过 onbeforeunload 控制在线人数,当用户直接关闭IE或转向时,把数据库中的在线状态更改成不在线。
    方法如下:
    页面文件
       <script type="text/javascript">
           function Exit()
           {
                if (event.clientX > document.body.clientWidth - 50 && event.clientY<0||event.altKey)
                   {
    //在 .CS文件中对应了一个方法,更改在线状态的
                     <%=exitLogin()%>;
                  
                   }
                   else
                   {
                      alert("刷新或者跳转到其他页");
                   }
                   
                   if(event.returnValue == false)              
                   {  
                       
                   }
           }        
       </script>

    <frameset rows="82, *, 5" id="frameSet" frameborder="0" onbeforeunload="Exit();">  </frameset>

    ------------------------------------------------------------------------------------------------
    CS文件。 


        public string exitLogin()
        {
    //更改用户在线状态
            PublicClass_Proc.ExecuteNonQuery(CommandType.StoredProcedure, "Proc_Logout", new SqlParameter("@userCode", User.Identity.Name));

            Session.RemoveAll();

            return "1";
        }

    ----------------

    不知道为什么当登录页面一指向这个页面,exitLogin()方法就会被执行。
    2009年1月16日 9:34

答案

  • onbeforeunload 是不可靠的,也是不好的做法。

    如果你想特别准确地控制,你可以在页面中加入定时器,去定时更新在线记录,如果更新的间隔大于某个设置的值,则认为不在线了。

     

    如果不想特别准确,可以使用 Session等默认的过期时间来控制。

     

     

     

    2009年1月17日 12:16
    版主

全部回复

  • 我不知道 我提出的问题 是不是会太打击您. 但我还是得告诉您 如何做正确的事.

     

    先说c#部分

    <%=exitLogin()%>;

    您这句在这里的作用是 Response.Write(exitLogin()); 那么就 直接先执行了 exitLogin方法了  自然每次 访问这个页面就先执行了该方法 然后向 aspx 输出该方法返回值 我想大概 是 1 .

     

    您的意思 大概是 想 当满足条件时 才执行那句. 问题是  c#的方法和js  是不可能直接 逻辑嵌套 使用的...

     

    您得知道 这是一个 client 和server 交互的过程 .所以如果要实现该功能 您需要 写一个独立的js方法  当该事件发生时 去异步或同步 调用服务器端的 c#方法

     

    其次  可能是我知识有限.  我不知道 frameset 是不是具备 onbeforeunload 事件  我以为 beforeunload 是window对象的 事件属性 .  不过也许能行   因为 浏览器 支持类似的写法  frameElement.document.body  它等同于 frameElement.window.document.body   那么可能  onbeforeunload事件 如果写在 frameset 标签内  则 可能有某种约定 会指向 frameElement.window对象上.

     

    再说说您的js判断 if (event.clientX > document.body.clientWidth - 50 && event.clientY<0||event.altKey)

    这个是为了大概判断 是刷新还是关闭 浏览器. 因为 unbeforeunload 和unload 事件 在刷新和 关闭 或跳转时 都会发生

    所以通过判断事件发生时 鼠标坐标来推断 是刷新 还是关闭 虽然您多考虑了一项 altKey 即 用户是不是 使用alt+f4关闭了 当前页.. 但很明显您没考虑 f5 刷新  而且  如果您使用了框架 . 则 坐标位置判断显然就 不可靠了.

    还有就是您的代码 很明显 event.altKey 这里只有ie有效

     

    其次 多标签浏览器 由于关闭标签 的方式太多. 所以您通过鼠标判断 就根本是不可能的任务...

     

    那么 最终.我给您的建议是 放弃这个功能 ..  其原因 和服务器端 无关. 主要是 js无法正确 可靠的判断 到底是刷新 还是跳转页 或关闭了 页面.

     

    如果您放弃 考虑刷新问题 则面临的问题 就是 一旦他刷新 您却清除了session 则他需要重新登陆...

    那么您非要实现 则必须不清除session或不强制session过期...   只做数据库读写 记录在线人数.. 但 很明显这样 给服务器带来的压力 也不小..  每次刷新读写一次数据....

     

    综合来说.还是建议您放弃该功能

    2009年1月16日 18:28
  • asp.net 在线用户统计还有什么别的好办法吗?哪位还知道啊?
    2009年1月17日 2:16
  • onbeforeunload 是不可靠的,也是不好的做法。

    如果你想特别准确地控制,你可以在页面中加入定时器,去定时更新在线记录,如果更新的间隔大于某个设置的值,则认为不在线了。

     

    如果不想特别准确,可以使用 Session等默认的过期时间来控制。

     

     

     

    2009年1月17日 12:16
    版主