单击后退按钮时是否有跨浏览器的 onload 事件?

IT技术 javascript pageload
2021-01-27 08:08:16

对于所有主流浏览器(IE 除外),JavaScriptonload事件在页面加载时由于后退按钮操作而不会触发——它仅在页面首次加载时触发。

有人可以指出一些解决此问题的跨浏览器示例代码(Firefox、Opera、Safari、IE 等)吗?我熟悉 Firefox 的pageshow事件,但不幸的是 Opera 和 Safari 都没有实现这一点。

6个回答

伙计们,我发现 JQuery 只有一种效果:按下后退按钮时重新加载页面。这与“就绪无关

这是如何运作的?好吧,JQuery 添加了一个onunload事件侦听器。

// http://code.jquery.com/jquery-latest.js
jQuery(window).bind("unload", function() { // ...

默认情况下,它什么都不做。但不知何故,这似乎在 Safari、Opera 和 Mozilla 中触发了重新加载——无论事件处理程序包含什么。

[编辑(尼古拉):这就是为什么它会这样工作:webkit.orgdeveloper.mozilla.org请阅读这些文章(或我在下面单独回答中的总结),并考虑您是否真的需要这样做并让您的用户的页面加载速度变慢。]

不敢相信?尝试这个:

<body onunload=""><!-- This does the trick -->
<script type="text/javascript">
    alert('first load / reload');
    window.onload = function(){alert('onload')};
</script>
<a href="http://stackoverflow.com">click me, then press the back button</a>
</body>

使用 JQuery 时您会看到类似的结果。

您可能想在没有onunload 的情况下与此进行比较

<body><!-- Will not reload on back button -->
<script type="text/javascript">
    alert('first load / reload');
    window.onload = function(){alert('onload')};
</script>
<a href="http://stackoverflow.com">click me, then press the back button</a>
</body>
它在 iPad Safari 中不起作用...请取消将其标记为答案
2021-03-14 08:08:16
这是因为如果浏览器有一个onunload处理程序,它就会假定页面是不可缓存的(页面已经销毁了所有内容;为什么要缓存它?)。
2021-03-16 08:08:16
答案似乎不适用于现代浏览器 - 已检查最新的 Chrome 和 Opera
2021-03-17 08:08:16
这也有效(不要忘记 onunload="" 部分,否则将无法在 ff3 上工作):<body onload="alert('onload');" onunload="">
2021-03-22 08:08:16
非常好..虽然这是一个未记录的功能/错误,并且可能会在浏览器的未来版本中停止工作,但它仍然很有趣。
2021-04-08 08:08:16

一些现代浏览器(Firefox、Safari 和 Opera,但不支持 Chrome)支持特殊的“后退/前进”缓存(我将其称为 bfcache,这是 Mozilla 发明的一个术语),当用户导航后退时会用到它。与常规(HTTP)缓存不同,它捕获页面的完整状态(包括 JS、DOM 的状态)。这允许它在用户离开页面时更快、更准确地重新加载页面。

load当页面从此 bfcache 加载时,不应触发事件。例如,如果您在“加载”处理程序中创建了 UI,并且在初始加载时触发了一次“加载”事件,第二次从 bfcache 重新加载页面时,页面将最终以重复的 UI 元素。

这也是为什么添加“卸载”处理程序会阻止页面存储在 bfcache 中的原因(从而使其导航回更慢)——卸载处理程序可以执行清理任务,这可能会使页面处于无法工作的状态。

对于需要知道何时被导航离开/返回的页面,Firefox 1.5+ 和修复了错误 28758的 Safari 版本支持称为“pageshow”和“pagehide”的特殊事件。

参考:

这很酷。我目前的情况是我的 dom 操作似乎没有保存在 bfcache 中。有没有您可能期望的情况?
2021-03-10 08:08:16
Nickolay,我知道您不愿意强制重新加载并撤消 bfcache 所做的出色工作,但是还有其他方法可以更新 bfcache 中页面的 dom 吗?例如,考虑这样一种情况:我从一个包含消息列表的页面转到其中一个,当我“返回”时,我希望已读/未读指示符发生变化。如何在不重新加载页面的情况下完成此操作?
2021-03-22 08:08:16
@Greg:您的意思是作为控制页面的开发人员?从“pageshow”侦听器发出 ajax 请求。
2021-03-29 08:08:16
@Benson:我链接到的 dev.mo 页面上列出了 Firefox 不会将您的页面保存在 bfcache 中的可能原因。我认为不可能将页面保存到 bfcache,但某些 DOM 状态不会被保存。
2021-03-31 08:08:16
关于如何使用 jQuery 并获得快速 bfcache 支持的任何想法?
2021-04-07 08:08:16

我遇到了一个问题,当用户点击后退或前进时,我的 js 没有执行。我首先开始阻止浏览器缓存,但这似乎不是问题。我的 javascript 设置为在加载所有库等之后执行。我用 readyStateChange 事件检查了这些。

经过一些测试,我发现点击返回的页面中元素的 readyState 不是“已加载”而是“已完成”。添加|| element.readyState == 'complete'到我的条件语句解决了我的问题。

只是想我会分享我的发现,希望他们能帮助别人。

编辑完整性

我的代码如下所示:

script.onreadystatechange(function(){ 
   if(script.readyState == 'loaded' || script.readyState == 'complete') {
      // call code to execute here.
   } 
});

在上面的代码示例中,脚本变量是一个新创建的脚本元素,它已添加到 DOM 中。

@Phillip 条件语句是 if 语句。
2021-03-16 08:08:16
当你说“我的条件语句”时,你是什么意思?
2021-03-25 08:08:16
你在哪里添加这个?在用户回击后,你是如何触发任何东西的?请向我们展示一些代码!
2021-04-09 08:08:16

好的,这是基于 ckramer 的初始解决方案和 Palehorse 的示例的最终解决方案,适用于所有浏览器,包括 Opera。如果您将 history.navigationMode 设置为 'compatible',那么 jQuery 的就绪功能将在 Opera 以及其他主要浏览器中触发后退按钮操作。

此页面有更多信息

例子:

history.navigationMode = 'compatible';
$(document).ready(function(){
  alert('test');
});

我在 Opera 9.5、IE7、FF3 和 Safari 中对此进行了测试,并且在所有这些中都有效。

显然已经有一段时间(大约 5.5 年)但值得注意的是您的链接已失效。
2021-03-21 08:08:16
这个解决方案对我不起作用。我在最新的 Firefox (45.0.1) 中遇到了这个问题
2021-03-25 08:08:16

我无法使上述示例起作用。我只是想在通过后退按钮返回页面时触发某些修改过的 div 区域的刷新。我使用的技巧是在 div 区域从原始区域更改后立即将隐藏的输入字段(称为“脏位”)设置为 1。当我点击返回时,隐藏的输入字段实际上保留了它的值,所以 onload 我可以检查这个位。如果设置,我刷新页面(或只是刷新 div)。然而,在原始加载时,该位未设置,因此我不会浪费时间加载页面两次。

<input type='hidden' id='dirty'>

<script>
$(document).ready(function() {
  if ($('#dirty').val()) {
    // ... reload the page or specific divs only
  }
  // when something modifies a div that needs to be refreshed, set dirty=1
  $('#dirty').val('1');
});
</script>

每当我单击后退按钮时,它都会正确触发。

虽然这在 Firefox 中不起作用,但我认为这是一种处理 IE/Chrome 中隐藏字段持久性非常有用的情况的巧妙方法。我已经使用了您的技巧以及“pageshow”事件,因此我涵盖了所有主要浏览器。
2021-03-26 08:08:16
什么浏览器不能与 pageshow 一起使用?
2021-03-29 08:08:16