Chrome中的页面重新加载在重新加载页面之前不必要地触发绑定事件

时间:2011-08-26 12:38:41

标签: javascript jquery google-chrome javascript-events google-chrome-devtools

希望有人对此有一个好的答案:

为什么Chrome(14.0)会在刷新页面时触发文档就绪和窗口加载事件?请注意,我不是在谈论新页面加载时会发生什么,而是在加载之前。请参阅以下代码:

<form name="form1" method="post" action="tmp.aspx?a=1" id="form1">
<script type="text/javascript">

    $(document).ready(function () { console.log('document/ready' + new Date()); });

    $(window).load(function () { console.log('window/load' + new Date()); });

</script>

<a href="tmp.aspx?a=1">tmp</a>
</form>

当我第一次访问页面时,我在控制台上获得两个输出,一个用于文档/就绪,一个用于窗口/加载。当我刷新页面时,会快速输出两个,并在此之后立即输出两个(从新页面视图)。如果我只是单击直接返回同一页面的链接(tmp.aspx),则不会发生这种情况。

我相信对此有一个很好的解释。

问候!

编辑: 在页面刷新之前,会对$(document).ready()和$(window).load()进行额外调用。因此,当我第一次加载页面时,他们的方法被调用一次,然后我点击刷新并且在页面重新加载之前再次调用方法。之后,当页面刚重新加载时,这些方法称为第三次。

6 个答案:

答案 0 :(得分:7)

于14.0.835.202观察到的行为。编辑:(在Windows 7 x64上)

这不是jquery错误:DOMContentLoaded在页面卸载之前的另一次被触发。

检查这个的简单测试:

 function startpage() {   
     console.log('page loaded');
   }   

   function unloadPage(){
       console.log("page unloaded");
   }
document.addEventListener("DOMContentLoaded", startpage, false);
window.onbeforeunload = unloadPage;

刷新后应该看到:

page loaded
page loaded // should not be here and is not on Firefox.
page unloaded
loaded

在你的控制台中(持久化)

我认为这只是一个Chrome错误。不是控制台,因为时间戳证明它不是重复的。

编辑:相同的Chrome版本,但运行OSX似乎没问题(请参阅下面的评论)。它倾向于证实这是一个错误。

答案 1 :(得分:3)

在Chrome 13 for Mac中,我没有看到这种行为。在您第一次加载页面之后,在您点击刷新之前,您是否清除了控制台?您是否有机会看到旧的控制台输出(我知道有些浏览器喜欢保留前一页的控制台输出)?

我不希望这两个事件在刷新时被触发两次,所以我的猜测是陈旧的控制台,无论是设计因为它是手动刷新还是Chrome 14都有他们的开发控制台的错误。

答案 2 :(得分:3)

只需添加一些测试说明,使用chrome 15.0.874.102和windows 7 x86:

这是我用来测试我对问题的测试的脚本:

<html>
    <head>
        <script language="javascript">
            var r = Math.floor(Math.random() * 101);

            function reloadLink() {
                console.log('----Reload Link----');
            }

            function startpage() {
                console.log('---Loaded. ID: ' + r + ' Time: '+new Date());
            }

            function unloadPage() {
                console.log('Un-loaded. ID: ' + r + ' Time: '+new Date());
            }

            document.addEventListener("DOMContentLoaded", startpage, false);
            window.onbeforeunload = unloadPage;

        </script>
        <title>Testing Chrome</title>
    </head>
    <body>
        <a href="" onclick="reloadLink();">Reload Page</a>
    </body>
</html>

以下是累积日志,每个新添加的内容都以粗体突出显示:

  • 在初始页面加载时,我得到:
  • ---加载。 ID:68时间:2011年10月25日星期二21:35:18 GMT + 0100(GMT日光时间)

  • 在专注于HTML页面的同时按F5:
  • ---加载。 ID:68时间:2011年10月25日星期二21:35:18 GMT + 0100(格林威治标准时间夏令时)
    ---加载。 ID:68时间:2011年10月25日星期二21:35:18 GMT + 0100(GMT日光时间)&lt; -----
    取消加载。 ID:68时间:2011年10月25日星期二21:36:12 GMT + 0100(GMT日光时间)
    ---加载。 ID:78时间:2011年10月25日星期二21:36:12 GMT + 0100(GMT日光时间)

  • 按HTML页面上的链接重新加载页面:
  • ---加载。 ID:68时间:2011年10月25日星期二21:35:18 GMT + 0100(格林威治标准时间夏令时)
    ---加载。 ID:68时间:2011年10月25日星期二21:35:18 GMT + 0100(格林威治标准时间夏令时)
    取消加载。 ID:68时间:2011年10月25日星期二21:36:12 GMT + 0100(GMT日光时间)
    ---加载。 ID:78时间:2011年10月25日星期二21:36:12 GMT + 0100(GMT夏令时)

    ----重新加载链接----
    取消加载。 ID:78时间:2011年10月25日星期二21:38:25 GMT + 0100(GMT日光时间)
    ---加载。 ID:22时间:2011年10月25日星期二21:38:25 GMT + 0100(GMT日光时间)

  • 在专注于控制台的同时按F5:
  • ---加载。 ID:68时间:2011年10月25日星期二21:35:18 GMT + 0100(格林威治标准时间夏令时)
    ---加载。 ID:68时间:2011年10月25日星期二21:35:18 GMT + 0100(格林威治标准时间夏令时)
    取消加载。 ID:68时间:2011年10月25日星期二21:36:12 GMT + 0100(GMT日光时间)
    ---加载。 ID:78时间:2011年10月25日星期二21:36:12 GMT + 0100(GMT日光时间)
    ----重新加载链接----
    取消加载。 ID:78时间:2011年10月25日星期二21:38:25 GMT + 0100(GMT日光时间)
    ---加载。 ID:22时间:2011年10月25日星期二21:38:25 GMT + 0100(GMT夏令时)

    取消加载。 ID:22时间:2011年10月25日星期二21:41:53 GMT + 0100(GMT日光时间)
    ---加载。 ID:15时间:2011年10月25日星期二21:41:54 GMT + 0100(格林威治标准时间夏令时)

    正如您所看到的,只有当直接重新加载页面(我用箭头突出显示异常)时才会出现异常,同时专注于页面本身。
    另外,如果你注意到异常的ID和时间戳,即使在点击F5之后等待几秒钟它们也是相同的 - 所以看起来代码没有再次运行,可以这么说,但是控制台出于某种原因正在记录副本。


    进一步补充结论:

    如果您选择时间线选项卡,并记录初始页面加载和F5重新加载,您会注意到写入控制台的两个函数只运行一次,进一步复合它看起来像是在chromes控制台上可能出错:

    Screenshot Show Image - Timeline 1 (initial load) Screenshot Show Image - Timeline 2 (F5 reload)

    答案 3 :(得分:2)

    据我所知,点击#xxx链接(或指向同一页面的链接,包括或不包含#xxx)都不会触发window.loaddocument.ready个事件。

    如果您希望链接触发事件,请执行类似

    的操作
    $('a#xxx').click(function(){
        //Your code here
    }
    

    其中xxx是链接的ID。

    如果链接是为了重新加载页面,请使用

    window.location.reload()
    
    单击事件处理程序中的

    答案 4 :(得分:2)

    我在Windows上的Chromium 14上测试了这个。没有观察到行为。

    答案 5 :(得分:2)

    这似乎是chrome / webkit开发人员控制台错误。在Ubuntu上使用chrome 14可以通过以下步骤重现该错误。

    首先创建一个包含以下js代码的页面

    var timesLoaded = 0;
    
    function loadHandler() {
        console.log(timesLoaded, "times loaded");
        timesLoaded++;
    }   
    
    function unloadHandler(){
        console.log("unload after ", timesLoaded, " loads");
    }
    
    $(document).ready(loadHandler);
    $(window).unload(unloadHandler);
    
    1. 使用谷歌浏览器打开页面
    2. 按F12打开控制台,查看0“次加载”消息
    3. 在unloadHandler函数的第一行添加断点
    4. 要查看双重消息,您应该点击页面上的某个位置(例如将焦点从控制台和加载的页面中提取出来)
    5. 刷新页面
    6. 您可能会再次看到0次“加载时间”消息
    7. 重要的是你的代码不会被执行两次。它只是由于某种原因webkit开发控制台再次显示相同的消息。要进一步调查该错误,您可以执行以下操作,

      1. 加载上一个html页面
      2. 再次添加卸载断点(只是为了确保页面不会实际刷新)
      3. 右键单击控制台第一个条目(0“载入次数”)
      4. 点击检查元素(是控制台只是一个html / js应用程序)
      5. 找到条目所属的元素(它应该是div.console-group-message元素
      6. 右键单击该元素,然后单击 Break on Subtree Modifications
      7. 刷新页面(再次点击html页面上的某处取消焦点控制台窗口
      8. 在第二个恼人的消息出现之前,调试器将显示尝试附加消息的控制台代码。