后退按钮导致iFrame延迟window.onLoad事件

时间:2010-12-28 23:24:38

标签: javascript firefox iframe javascript-events

我通过iFrame投放广告。广告网络的服务器比我的慢很多,所以我在window.onload事件上异步加载iFrame。

// (using Prototype library)
Event.observe(window, 'load', function() {
  $('ad').writeAttribute('src', '/ad.html');
  // other initialization here
});

通过浏览器的后退按钮进入网站时出现问题。出乎意料的是,广告iFrame尝试立即加载(在上面的加载侦听器设置'src'属性之前),将load事件延迟几秒钟。在这几秒钟内,该站点无法使用,因为我在window.onload中进行了一系列初始化。

据我所知,这只发生在Firefox中。如何防止此阻塞负载?

4 个答案:

答案 0 :(得分:2)

问题可能是Firefox的bfcache(后退/前进缓存),它使用后退和前进按钮保持页面加载以便更快地导航。您可以通过绑定卸载处理程序为页面禁用它。

答案 1 :(得分:1)

理论

您注意到的问题可以这样描述:文档中的iframe在外部页面导航时加载其中加载的URL,而不是外部页面HTML源中指定的URL(或空在您的情况下页面。)

它延迟onload的事实只是一个必然结果:加载事件被延迟,直到所有资源(图像,帧等)都完成加载。

我找不到文档说明它应该以这种方式发生,也没有任何错误报告承认它是一个已知问题,但是FWIW我在下面的测试用例中看到与Google Chrome 10.0.612.3完全相同的行为。

这种行为即使在您的情况下不直观,也有一些逻辑:历史上帧中的文档加载记录在会话历史记录中(后退/前进导航历史记录)。假设您打开一个网站,其主要内容在框架中,并导航内部iframe。离开网站后,通过后退按钮返回,浏览器应该可以在框架中加载最后加载​​的页面。

解决方案

令人惊讶的是,这似乎不是一个常见问题,因此这些建议是基于我对该问题的理解,我没有在任何情况下测试它们比下面的测试用例更真实。

  1. 如果您使bfcache工作,那么用户的最佳体验就是。据我所知,这将要求广告文档可缓存(使用不同的URL来显示不同的广告),并可能更改您使用的JS框架(如果碰巧总是打破bfcache,我不知道,这曾经是其他框架的问题) 如果你把它拉了下来,根本就没有load事件,页面就会完全恢复到它所处的状态,而且它比任何碰到网络的东西都要快得多。
  2. 阻止iframe加载会话历史记录中的URL的唯一方法我可以想到的是避免在HTML源代码中使用iframe。如果您动态插入它,下次加载页面时它将不是“相同”的iframe,因此默认为您在src中指定的URL。
  3. 您可以使iframe不会阻止当前正在运行load事件的代码,而不是阻止iframe在“返回”时加载广告。为此,您可以使用DOMContentLoaded事件。
  4. 附录:测试用例

    <iframe id="a"></iframe>
    <pre id="b"></pre>
    <script>
    var b = document.getElementById("b")
    b.innerHTML += "before 'load': iframe src=" + document.getElementById("a").src + "\n";
    window.addEventListener("load", function() {
      var newURL = "https://developer.mozilla.org/en/HTML/Element/iframe";
      b.innerHTML += "onload: iframe src=" + document.getElementById("a").src + "\n";
      b.innerHTML += "setting src to " + newURL + "\n";
      document.getElementById("a").src = newURL;
      b.innerHTML += "now iframe src=" + document.getElementById("a").src + "\n";
    }, false);
    
    // disable bfcache
    window.onunload = function() {}
    </script>
    

答案 2 :(得分:0)

值得尝试的是延迟writeAttribute,直到处理完其余的事件:

Event.observe(
 window,
 'load',
 function() {
  setTimeout(function() { 
    $('ad').writeAttribute('ad.html');
  }, 0);
 }
);

这将在其他所有内容完成后立即执行。

答案 3 :(得分:0)

值得尝试的是延迟writeAttribute,直到处理完其余的事件:

Event.observe(
 window,
 'load',
 function() {
  setTimeout(function() { 
    $('ad').writeAttribute('ad.html');
  }, 0);
 }
);

这将在其他所有内容完成后立即执行。

嗯,我不会让我提出两个答案

我不知道为什么会发生这种情况,但您尝试在您的网页和广告之间添加另一个 iframe:您的网页会加载iframe; iframe等待几秒钟(让你的页面加载),然后加载广告,这将占用中间iframe的整个区域。