返回Firefox历史记录后,JavaScript将无法运行


84

当我使用Firefox上的“后退”按钮访问先前访问过的页面时,该页面上的脚本将不会再次运行

是否有任何修复/替代方法可让脚本在第二次查看页面时再次执行?

请注意,我已经在Google Chrome和Internet Explorer上测试了相同的页面,它们可以正常工作。


这是我用来测试问题的文件和步骤:

(导航至0.html,单击以获取1.html,后退按钮)

0.html

<html><body>
<script>
  window.onload = function() { alert('window.onload alert'); };
  alert('inline alert');
</script>
<a href="1.html">Click Me!</a>
</body></html>

1.html

<html><body>
<p>Go BACK!</p>
</body></html>

Answers:


92

设置要在window.onunload上调用的空函数:

window.onunload = function(){}; 

例如

<html><body>
<script type="text/javascript">
  window.onload = function() { alert('window.onload alert'); };
  window.onunload = function(){};
  alert('inline alert');
</script>
<a href="1.html">Click Me!</a>
</body></html>

来源: http //www.firefoxanswer.com/firefox/672-firefoxanswer.html (存档版本)


2
谢谢,它有效。关于默认onunload处理函数的任何提示?(例如,我是否在此处覆盖某种默认行为?)
Patonza 2010年

好的,谢谢,我会调查。再次感谢您,这个问题困扰了我一段时间:)
Patonza 2010年

有人知道为什么FireFox需要此功能而其他浏览器却不需要吗?
Pim Jager 2010年

7
您没有覆盖任何内容,这只是防止Firefox在Back-Forward Cache(bfcache)中缓存页面。developer.mozilla.org/en/DOM/window.onunload developer.mozilla.org/En/Using_Firefox_1.5_caching
Chris Haas 2010年

1
不幸的是,尽管它应该中断bfcache,但它似乎仍然记得上一页-特别是,当您返回时,已加载的iframe网址会再次加载,并且如果生成的内容需要放置在框架中,则似乎没有跨浏览器重新刷新的方式。
NoBugs 2015年

76

当我使用Firefox上的“后退”按钮访问先前访问的页面时,该页面上的脚本将不会再次运行。

没错,那是一件好事。

当您在Firefox(以及Safari和Opera)中单击链接时,它不会立即破坏您的页面以转到下一个页面。它使页面保持完整,仅将其隐藏起来。如果单击后退按钮,它将使旧页面重新显示,而无需再次加载文档。这样会更快,从而使用户的后退/前进页面转换更加顺畅。

此功能称为bfcache

在用户上一次加载和使用该页面期间添加到该页面的任何内容仍将在那里。您附加到页面元素的任何事件处理程序仍将附加。您设置的任何超时/间隔仍然有效。因此,几乎没有任何理由需要知道您已被隐藏并重新显示。onload再次调用或内联脚本代码是错误的,因为您在该函数中执行的任何绑定和内容生成都将在同一内容上第二次执行,从而可能导致灾难性的后果。(例如document.write,内联脚本将完全破坏该页面。)

写入会window.onunload产生影响的原因是,实现bfcache的浏览器已经决定-为了与确实确实需要知道何时被丢弃的页面兼容,任何声明有兴趣知道何时onunload发生的页面都将导致bfcache停止运行。被禁用。返回该页面时将重新加载该页面,而不是从bfcache获取。

因此,如果您设置window.onunload= function() {};,那么您实际上正在做的是故意破坏bfcache。这将导致您的页面导航缓慢,除非万不得已,否则请勿使用。

如果您确实需要知道用户何时离开或返回页面,而又不会弄乱bfcache,则可以捕获onpageshowonpagehide事件:

window.onload=window.onpageshow= function() {
    alert('Hello!');
};

3
我的问题是bfcache不会缓存所有页面,因此我必须重新运行js才能重建丢失的内容。因此,对整个页面进行修改是可以的。无论如何,我不是在使用window.onload事件,而是在使用jQuery document.ready事件。您知道仍然可以使用document.ready并避免此问题的方法吗?
Patonza 2010年

bfcache通常应该返回整个页面,就像它离开时一样。从上一页返回后缺少的内容是什么?(测试用例?)的document.ready工作方式基本上与window.onload(对于某些浏览器,它们仍然是同一事件)。
bobince 2010年

14
那不是一件好事,因为考虑到已缓存它,它不会再次运行javascript ...但是实际上并没有缓存javascript之前所做的更改。如果javascript在页面加载时淡入一个元素,则在历史记录中访问时它不会再次淡入它...但是确实会在0透明度下再次启动它,从而撤消了javascript所做的工作!它必须是全部或全部。如果要显示已缓存的页面而不再次运行javascript,则必须在运行javascript后缓存页面的完整状态!
Jimbo Jonny 2012年

1
@Jimbo:请测试用例。bfcache旨在(并且在我所见过的每种情况下都可以)通过隐藏/显示保留DOM的确切状态。返回页面时,淡入的元素将保持不透明,除非运行其他脚本再次将其隐藏。
bobince 2012年

1
@bobince-使用CSS文件制作一个将不透明度设置为零的元素,然后使用一些jQuery使它在准备就绪的文档中淡入。回顾历史,它将重新应用样式表CSS(零),而不会保持JS在淡入时添加到样式属性中的不透明度:1。第一次访问页面时,该元素将从零淡入。转到另一页并回击,它将完全透明地坐在那里。
Jimbo Jonny 2012年

23

您可以检查事件的persisted属性pageshow。初始页面加载时将其设置为false。从缓存加载页面时,将其设置为true。

window.onpageshow = function(event) {
    if (event.persisted) {
        alert("From bfcache");
    }
};

出于某种原因,jQuery事件中没有此属性。您可以从原始事件中找到它。

$(window).bind("pageshow", function(event) {
    if (event.originalEvent.persisted) {
        alert("From bfcache");
    }
});

感谢您提供javascript和jquery版本!您错过了结尾处的右括号(这不是a吟!)。出于其他原因,我还将注意到IE和Chrome报告.persisted始终为假,无论如何。
Magnus Smith

正如Magnus指出的那样,直到我删除了if语句,Chrome才对我不起作用。
贾斯汀

这在Chrome 58.0.3029.110(64位)和FF ​​53.0.2(64位)中对我有效,没有任何更改。
kmoser

1

连接一个不执行任何操作的“ onunload”事件:

<html><body>
<script type="text/javascript">
  window.onload = function() { alert('window.onload alert'); };
  window.onunload = function(){}; 
  alert('inline alert');
</script>
<a href="1.html">Click Me!</a>
</body></html>

不确定,我投了反对票,好像有人对这个问题的每个答案都投了反对票...
Patonza 2010年

您应该在答案中添加以下内容:在页面上添加onunload事件实际上将完全禁用正在缓存的页面。这不仅会使JS重新运行,还会使服务器负载增加一个档次。这确实不是一个轻率的建议,应该仔细考虑。
dreagan 2015年

@dreagan,这将禁用bfcache,但不一定禁用HTTP缓存。HTTP缓存具有其他完整的规则集。如果您将服务器端睡眠置于其中,则应在单击返回时注意到它。Mozilla在有关BFCacheFAQ的第三个问题中谈到了这一点
克里斯·哈斯

我在谈论BFcache,应该已经指定了。这并不意味着您应该在不通知OP后果的情况下给出这样的建议。一种替代方法是使用onpopstate事件尝试再次触发javascript。
dreagan

我还是不知道我是否理解。如果绕过客户端的本地bfcache,为什么“服务器负载会增加”?是的,将需要重新构建DOM,但是HTML应该是客户端HTTP缓存的一部分。是的,将需要重新加载其他资源,但是这些资源也应该是客户端HTTP缓存的一部分。至于,onpopstate大约在五年前提出这个问题时,该事件仍相对较新,浏览器支持也非常不一致
Chris Haas

1

据我所知,Firefox不会触发onLoad事件。

它应改为从这个链接基于触发的onfocus这里


经过测试,即使没有设置空的window.onunload处理程序,确实会调用windows.onfocus。设置onunload是一个更好的解决方法,但是.onfocus也应该很好。谢谢:)
Patonza 2010年

1

当用户使用浏览器历史记录导航回页面时,使页面执行JavaScript的一种简单方法是OnPopState事件。我们使用它来暂停并在我们的主页(https://fynydd.com)上回放视频。

window.onpopstate = function() {

    // Do stuff here...
};

0

在某些情况下,例如ajax操作,可以使用url更改监听器

$(window).on('hashchange', function() {
        ....
});
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.