点击后退按钮时是否存在跨浏览器onload事件?
对于所有主要浏览器(IE 除外),当由于后退按钮操作而加载页面时,JavaScript onload
事件不会触发 - 它仅在页面首次加载时触发。
有人可以给我指出一些解决这个问题的示例跨浏览器代码(Firefox、Opera、Safari、IE...)吗?我熟悉 Firefox 的 pageshow
事件,但不幸的是 Opera 和 Safari 都没有实现这一点。
For all major browsers (except IE), the JavaScript onload
event doesn’t fire when the page loads as a result of a back button operation — it only fires when the page is first loaded.
Can someone point me at some sample cross-browser code (Firefox, Opera, Safari, IE, …) that solves this problem? I’m familiar with Firefox’s pageshow
event but unfortunately neither Opera nor Safari implement this.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(16)
伙计们,我发现 JQuery 只有一种效果:按下后退按钮时重新加载页面。这与“准备就绪”无关。
这是如何运作的?嗯,JQuery 添加了一个 onunload 事件监听器。
默认情况下,它不执行任何操作。但不知何故,这似乎会触发 Safari、Opera 和 Mozilla 中的重新加载——无论事件处理程序包含什么。
[编辑(Nickolay):这就是为什么它会这样工作:webkit.org, developer.mozilla.org。请阅读这些文章(或我在下面的单独答案中的总结),并考虑您是否真的需要这样做并让您的用户的页面加载速度变慢。]
不敢相信?试试这个:
使用 JQuery 时您会看到类似的结果。
您可能想与没有 onunload 的这个进行比较
Guys, I found that JQuery has only one effect: the page is reloaded when the back button is pressed. This has nothing to do with "ready".
How does this work? Well, JQuery adds an onunload event listener.
By default, it does nothing. But somehow this seems to trigger a reload in Safari, Opera and Mozilla -- no matter what the event handler contains.
[edit(Nickolay): here's why it works that way: webkit.org, developer.mozilla.org. Please read those articles (or my summary in a separate answer below) and consider whether you really need to do this and make your page load slower for your users.]
Can't believe it? Try this:
You will see similar results when using JQuery.
You may want to compare to this one without onunload
一些现代浏览器(Firefox、Safari 和 Opera,但不包括 Chrome)支持特殊的“后退/前进”缓存(我将其称为 bfcache,这是 Mozilla 发明的术语),当用户导航“后退”时会涉及到该缓存。与常规(HTTP)缓存不同,它捕获页面的完整状态(包括JS、DOM的状态)。这使得它能够更快地重新加载页面,并且与用户离开时的页面完全相同。
从该 bfcache 加载页面时,不应触发
load
事件。例如,如果您在“load”处理程序中创建了 UI,并且“load”事件在初始加载时触发一次,第二次从 bfcache 重新加载页面时,页面最终会显示重复的 UI 元素。这也是为什么添加“卸载”处理程序会阻止页面存储在 bfcache 中(从而使其导航回的速度变慢)——卸载处理程序可能会执行清理任务,这可能会使页面处于无法工作的状态。
对于需要知道何时导航离开/返回的页面,请使用 Firefox 1.5+ 和 Safari 版本,并修复 bug 28758 支持称为“pageshow”和“pagehide”的特殊事件。
参考资料:
Some modern browsers (Firefox, Safari, and Opera, but not Chrome) support the special "back/forward" cache (I'll call it bfcache, which is a term invented by Mozilla), involved when the user navigates Back. Unlike the regular (HTTP) cache, it captures the complete state of the page (including the state of JS, DOM). This allows it to re-load the page quicker and exactly as the user left it.
The
load
event is not supposed to fire when the page is loaded from this bfcache. For example, if you created your UI in the "load" handler, and the "load" event was fired once on the initial load, and the second time when the page was re-loaded from the bfcache, the page would end up with duplicate UI elements.This is also why adding the "unload" handler stops the page from being stored in the bfcache (thus making it slower to navigate back to) -- the unload handler could perform clean-up tasks, which could leave the page in unworkable state.
For pages that need to know when they're being navigated away/back to, Firefox 1.5+ and the version of Safari with the fix for bug 28758 support special events called "pageshow" and "pagehide".
References:
我遇到了一个问题,当用户单击后退或前进时,我的 js 没有执行。我首先着手阻止浏览器缓存,但这似乎不是问题。我的 javascript 设置为在加载所有库等后执行。我用readyStateChange事件检查了这些。
经过一些测试后,我发现单击“后退”的页面中元素的 ReadyState 不是“已加载”而是“完成”。添加 <代码>|| element.readyState == 'complete' 我的条件语句解决了我的问题。
只是想分享我的发现,希望它们能帮助其他人。
编辑完整性
我的代码如下所示:
在上面的代码示例中,脚本变量是一个新创建的脚本元素,已添加到 DOM 中。
I ran into a problem that my js was not executing when the user had clicked back or forward. I first set out to stop the browser from caching, but this didn't seem to be the problem. My javascript was set to execute after all of the libraries etc. were loaded. I checked these with the readyStateChange event.
After some testing I found out that the readyState of an element in a page where back has been clicked is not 'loaded' but 'complete'. Adding
|| element.readyState == 'complete'
to my conditional statement solved my problems.Just thought I'd share my findings, hopefully they will help someone else.
Edit for completeness
My code looked as follows:
In the code sample above the script variable was a newly created script element which had been added to the DOM.
好的,这是基于 ckramer 的初始解决方案和 Palehorse 的示例的最终解决方案,该解决方案适用于所有浏览器,包括 Opera。如果将history.navigationMode设置为“兼容”,那么jQuery的ready函数将在Opera以及其他主要浏览器中的后退按钮操作上触发。
此页面有更多信息< /a>.
示例:
我在 Opera 9.5、IE7、FF3 和 Safari 中对此进行了测试,它适用于所有这些版本。
OK, here is a final solution based on ckramer's initial solution and palehorse's example that works in all of the browsers, including Opera. If you set history.navigationMode to 'compatible' then jQuery's ready function will fire on Back button operations in Opera as well as the other major browsers.
This page has more information.
Example:
I tested this in Opera 9.5, IE7, FF3 and Safari and it works in all of them.
我无法让上面的例子工作。我只是想在通过后退按钮返回页面时触发某些修改后的 div 区域的刷新。我使用的技巧是,一旦 div 区域与原始区域发生变化,就将隐藏输入字段(称为“脏位”)设置为 1。当我点击返回时,隐藏的输入字段实际上保留了它的值,因此在加载时我可以检查这一点。如果已设置,我将刷新页面(或仅刷新 div)。然而,在原始加载时,该位未设置,因此我不会浪费时间加载页面两次。
每当我单击后退按钮时,它都会正确触发。
I couldn't get the above examples to work. I simply wanted to trigger a refresh of certain modified div areas when coming back to the page via the back button. The trick I used was to set a hidden input field (called a "dirty bit") to 1 as soon as the div areas changed from the original. The hidden input field actually retains its value when I click back, so onload I can check for this bit. If it's set, I refresh the page (or just refresh the divs). On the original load, however, the bit is not set, so I don't waste time loading the page twice.
And it would trigger properly whenever I clicked the back button.
我可以向 ckramer 确认 jQuery 的就绪事件可以在 IE 和 FireFox 中运行。这是一个示例:
I can confirm ckramer that jQuery's ready event works in IE and FireFox. Here's a sample:
如果我没记错的话,那么添加 unload() 事件意味着该页面无法被缓存(在前向/后向缓存中) - 因为当用户离开时它的状态发生变化/可能会发生变化。因此,当通过历史对象导航返回页面时,恢复页面的最后一秒状态是不安全的。
If I remember rightly, then adding an unload() event means that page cannot be cached (in forward/backward cache) - because it's state changes/may change when user navigates away. So - it is not safe to restore the last-second state of the page when returning to it by navigating through history object.
我认为这将用于“onunload”,而不是页面加载,因为我们不是在谈论点击“后退”时触发事件吗? $document.ready() 用于页面加载时所需的事件,无论您如何到达该页面(即重定向、直接打开浏览器到 URL 等),而不是单击“后退”时,除非您正在说话关于再次加载时在上一页上触发的内容。而且我不确定页面没有被缓存,因为我发现 Javascript 仍然被缓存,即使 $document.ready() 包含在其中。每当我们修改脚本并希望在页面中测试结果时,我们在编辑具有此事件的脚本时都必须按 Ctrl+F5。
是您在点击“返回”并卸载当前页面时想要的 onunload 事件,并且当用户关闭浏览器窗口时也会触发。这听起来更像是所期望的,即使我的 $document.ready() 响应数量超过了我。基本上,区别在于当前页面关闭时触发的事件与加载时单击“返回”时加载的事件之间的区别。在 IE 7 中测试得很好,不能代表其他浏览器,因为我们所在的地方不允许使用它们。但这可能是另一种选择。
I thought this would be for "onunload", not page load, since aren't we talking about firing an event when hitting "Back"? $document.ready() is for events desired on page load, no matter how you get to that page (i.e. redirect, opening the browser to the URL directly, etc.), not when clicking "Back", unless you're talking about what to fire on the previous page when it loads again. And I'm not sure the page isn't getting cached as I've found that Javascripts still are, even when $document.ready() is included in them. We've had to hit Ctrl+F5 when editing our scripts that have this event whenever we revise them and we want test the results in our pages.
is what you'd want for an onunload event when hitting "Back" and unloading the current page, and would also fire when a user closes the browser window. This sounded more like what was desired, even if I'm outnumbered with the $document.ready() responses. Basically the difference is between an event firing on the current page while it's closing or on the one that loads when clicking "Back" as it's loading. Tested in IE 7 fine, can't speak for the other browsers as they aren't allowed where we are. But this might be another option.
jQuery 的 ready 事件就是为了此类问题而创建的。您可能想深入了解实施情况,看看幕后发生了什么。
jQuery's ready event was created for just this sort of issue. You may want to dig into the implementation to see what is going on under the covers.
对于那些不想使用整个 jquery 库的人,我在单独的代码中提取了实现。它只有 0.4 KB 大。
您可以在此 wiki 中找到代码以及德语教程: http://www.easy-coding.de/wiki/html-ajax-und-co/onload -event-cross-browser-kompatibler-domcontentloaded.html
for the people who don't want to use the whole jquery library i extracted the implementation in separate code. It's only 0,4 KB big.
You can find the code, together with a german tutorial in this wiki: http://www.easy-coding.de/wiki/html-ajax-und-co/onload-event-cross-browser-kompatibler-domcontentloaded.html
比尔,我敢回答你的问题,但我不能百分百确定我的猜测。我认为其他 IE 浏览器在将用户带到历史页面时不仅会从缓存加载该页面及其资源,还会为其恢复整个 DOM(读取会话)状态。 IE 不执行 DOM 恢复(或者至少不执行),因此 onload 事件对于正确的页面重新初始化来说似乎是必要的。
Bill, I dare answer your question, however I am not 100% sure with my guesses. I think other then IE browsers when taking user to a page in history will not only load the page and its resources from cache but they will also restore the entire DOM (read session) state for it. IE doesn't do DOM restoration (or at lease did not do) and thus the onload event looks to be necessary for proper page re-initialization there.
我使用 $(document).ready... 尝试了 Bill 的解决方案,但一开始它不起作用。我发现如果脚本放在html部分之后,它将不起作用。如果是 head 部分,它可以工作,但只能在 IE 中使用。该脚本在 Firefox 中不起作用。
I tried the solution from Bill using $(document).ready... but at first it did not work. I discovered that if the script is placed after the html section, it will not work. If it is the head section it will work but only in IE. The script does not work in Firefox.
好的,我尝试过,它可以在 Firefox 3、Safari 3.1.1 和 IE7 中运行,但在 Opera 9.52 中不行。
如果您使用下面所示的示例(基于 Palehorse 的示例),则在页面首次加载时会弹出一个警告框。但是,如果您随后转到另一个 URL,然后单击“后退”按钮返回到此页面,则在 Opera 中不会弹出警告框(但在其他浏览器中会弹出警告框)。
无论如何,我认为现在已经足够接近了。谢谢大家!
OK, I tried this and it works in Firefox 3, Safari 3.1.1, and IE7 but not in Opera 9.52.
If you use the example shown below (based on palehorse's example), you get an alert box pop-up when the page first loads. But if you then go to another URL, and then hit the Back button to go back to this page, you don't get an alert box pop-up in Opera (but you do in the other browsers).
Anyway, I think this is close enough for now. Thanks everyone!
卸载事件在 IE 9 上无法正常工作。我尝试使用加载事件 (onload()),它在 IE 9 和 FF5 上工作正常。
示例:
Unload event is not working fine on IE 9. I tried it with load event (onload()), it is working fine on IE 9 and FF5.
Example:
我使用了一个html模板。在这个模板的custom.js文件中,有一个这样的函数:
但是当我转到其他页面后返回时,这个函数不起作用。
所以,我尝试了这个,它成功了:
现在,我有 2 个“就绪”功能,但它没有给出任何错误,并且页面运行良好。
尽管如此,我必须声明它已经在 Windows 10 - Opera v53 和 Edge v42 上进行了测试,但没有在其他浏览器上进行了测试。请记住这一点...
注意:jquery 版本是 3.3.1,migrate 版本是 3.0.0
I have used an html template. In this template's custom.js file, there was a function like this:
But this function was not working when I go to back after go to other page.
So, I tried this and it has worked:
Now, I have 2 "ready" function but it doesn't give any error and the page is working very well.
Nevertheless, I have to declare that it has tested on Windows 10 - Opera v53 and Edge v42 but no other browsers. Keep in mind this...
Note: jquery version was 3.3.1 and migrate version was 3.0.0
我正在构建一个基于 file:/// 协议的网站。 (Firefox 116.0.1 64位)所以这可能不适用于这里的许多情况:
但是,当我使用后退按钮到达包含运行该页面所需的脚本的页面时,它会失败。单击该页面的链接不会失败。
失败的定义:
浏览器选项卡将锁定并变得无响应,需要关闭。浏览器的后退、前进和停止按钮不可点击。
当我尝试
onunload=""
时,同样的失败随之而来......但是,当我为 onunload 设置一个真正的函数并让它调用正文的 onload 属性中描述的函数时tag ,开始重新加载所需的 javasript。
例子:
I am building a file:/// protocol based website. (Firefox 116.0.1 64bit ) So this may not apply to many situations here:
But , when I used the back button to reach a page with scripts that were required to run the page , it would fail. Clicking a link to the page would not fail.
Definition of failing:
Browser tab would lock up and become unresponsive and would require being closed. The browsers Back , Forw , and Stop Buttons were not clickable.
When I tried
onunload=""
, the same failure ensued...But , when I set up a real function for the onunload AND had it call the function that was described in the onload attribute of the body tag , is started reloading the needed javasript.
Example: