浏览器返回按钮不会触发onLoad事件

  最近在做一个移动端项目,发现移动端某些返回和PC端是有差异的, 比如ios中返回按钮是直接使用缓存的, 不会执行任何js代码, 这个问题很蛋疼, 例如, 在提交的时候将按钮设置为loading状态, 如果在提交成功后没有对安装进行处理, 那么返回后按钮依然是loading状态, 这种体验很差, 如下图:

此问题是由于某些浏览器在back的时候是直接使用的之前的视图,页面没有进行重新加载而导致的,在网上找了些资料, 发现这是H5的一些新特性Back-Forward Cache(简称bfcache) ,普通浏览器在back时,如果不是指定Cache-Control、Expires等方法强制停用Cache时,那么一般情况下浏览器大多数都会直接读取本地的缓存, 减少请求和网络传输的成本, 增加浏览的顺从度, 但Cache仅限于静态文件, 浏览器还是得重新加载html, 重新执行脚本,渲染DOM, 而bfcache则不同, 是直接读取缓存里面的html,节省了重新请求页面的时间, 既然是读取缓存的html页面, 那么执行页面的onload事件进行初始化, 会影响原本因用户操作而改变的状态, 所以浏览器在back时是不会触发onload事件.

这个时候就会产生上面的问题, 有些业务在返回时是需要重新加载的, 于是H5新增了两个事件onpageshow和onpagehide, 分别是进入网页和离开的时候触发, 即使是用浏览器的前进/后退也会触发这两个事件.

 1 <!DOCTYPE html>
 2
 3 <html>
 4 <head>
 5     <title>Page Events</title>
 6     <script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.7.2.js"></script>
 7     <script>
 8         function dispLog(msg) {
 9             var d = new Date();
10             $("<li />").text(d.toISOString().substr(14, 9) + " " + msg)
11             .appendTo("#dvDisp");
12
13         }
14         $(window).load(function () {
15             dispLog("Load Event");
16         }).ready(function () {
17             dispLog("Ready Event");
18             $("#btnSetColor").click(function () {
19                 $("a").css("color", "red");
20             });
21         }).bind("pageshow", function () {
22             dispLog("PageShow Event");
23         }).bind("pagehide", function () {
24             dispLog("PageHide Event");
25         });
26     </script>
27 </head>
28 <body>
29 <a href="test1.html">前往其它页面</a>
30 <input type="button" id="btnSetColor" value="变色" />
31 <ul id="dvDisp"></ul>
32 </body>
33 </html>

页面很简单, 绑定onload, ready,onpageshow,onpagehide四个事件, 触发事件相应的文本会显示在页面上, 另外这里有个连接可跳转到其它网页,便于测试back, button事件会改变连接的颜色, 便于back时检查颜色是否保留,判断是否有bfcache.

测试步骤打开test.html, 点击变色按钮, 再点击"前往其它页面", 然后在test1.html点击back按钮回到test.html. 在几次测试后, 大致的测试结果如下:

IE9
打开页面或则back时都会触发Ready/Load事件, 红色未保留, 无bfcache.
IE10 (Windows 8 Release Preview)
打开页面或则back时都会触发Ready/Load事件, 红色未保留, 无bfcache.
Chrome 21.0.1180.6
打开页面或则back时都会触发Ready/Load/PageShow事件, 红色未保留, 无bfcache.
Firefox 15.0
打开页面或则back时都会触发Ready/Load/PageShow事件,点击[前往其它网页]会触发PageHide, [back]时会触发PageShow, 红色被保留, 有bfcache.
Safari 5.1.5
打开页面或则back时都会触发Ready/Load/PageShow事件,点击[前往其它网页]会触发PageHide, [back]时会触发PageShow, 红色被保留, 有bfcache.
Safari on iPad (iOS 5.1.1)
打开页面或则back时都会触发Ready/Load/PageShow事件,点击[前往其它网页]会触发PageHide, [back]时会触发PageShow, 红色被保留, 有bfcache.
Opera 12.00
打开页面或则back时都会触发Ready/Load事件, [back]时会触发PageShow, 红色被保留, 有bfcache但不会触发PageShow事件.

总结: Firefox和Safari会bfcache, back时不会触发load, ready事件, 只会触发onpageshow, 而chrome虽然支持onpageshow, 但是back时一样都会触发load,ready事件, opera最操蛋, back时会bfcache,但是不触发onpageshow事件.

回到上面的问题, 如何解决bfcache时ready在back时不执行的问题呢?

起初是想新增一个$.pageshow(), 若浏览器支持, 将业务代码放在onpageshow事件里面处理, 否则用ready处理, 如下:

 1 $.pageshow = function (fn) {
 2     if (typeof window.onpageshow == "undefined")
 3         $(document).ready(fn);
 4     else
 5         $(window).bind("pageshow", fn);
 6 };
 7 $.pageshow(function () {
 8     alert("Page Show");
 9     alert(typeof window.onpageshow == "undefined")
10 });

很艹蛋啊, 这个方法只能解决Firefox、Safaer上的问题, 但是在Opera上就没什么效果.

还好在MDC的文档上找到一点思路, Firefox在某些条件下禁用bfcache:

There are instances in which Firefox doesn’t cache pages. Below are some common programmatic reasons that a page is not cached:

the page uses an unload or beforeunload handler;
the page sets "cache-control: no-store".
the site is HTTPS and page sets at least one of:
"Cache-Control: no-cache"
"Pragma: no-cache"
with "Expires: 0" or "Expires" with a date value in the past relative to the value of the "Date" header (unless "Cache-Control: max-age=" is also specified);
the page is not completely loaded when the user navigates away from it or has pending network requests for other reasons (e.g. XMLHttpRequest));
the page has running IndexedDB transactions;
the top-level page contains frames (e.g. <iframe> ) that are not cacheable for any of the reasons listed here;
the page is in a frame and the user loads a new page within that frame (in this case, when the user navigates away from the page, the content that was last loaded into the frames is what is cached).

想了下如果Firefox可以这样, Safari和Chrome应该也可以, 于是找到一个非常简单的方法来解决这个问题, 并且兼容Firefox、Safari、Opera, 只要在页面中加入下面的代码:

$(window).unload(function () { });

经过测试, 页面上一点绑定unload事件, Firefox/Safari/Opera等浏览器变会认为该页面不需要bfcache, 回归到传统的Cache模式, 这样就能解决back时不触发onload, ready等事件带来的问题了.

下面有两个连接, 不过解决问题的思路都差不多.

http://stackoverflow.com/questions/11979156/mobile-safari-back-button

http://stackoverflow.com/questions/24046/the-safari-back-button-problem

时间: 2024-08-27 07:56:03

浏览器返回按钮不会触发onLoad事件的相关文章

微信浏览器 返回按钮二次返回

在做微信开发的时候,当通过微信的推送消息(页面1)打开网页后(进入页面2),此时,再次打击链接打开网页(页面3).当点击安卓手机的返回按钮时,可以正常回退到"页面2",但是当点击微信左上角的返回按钮时,会直接回退到"页面1". 起初感觉是加载浏览器插件的原因,思考了好久不得结果.后来发现"招商银行信用卡中心"官方微信,并不存在上述问题.观察招商银行的官方微信发现,页面2的title是微信定义的title,但是页面3的title变成了用户自定义的t

网页提交,点击浏览器返回按钮,网页出错

这两天公司新项目写一个问卷调查小功能,当时因为问题都是循环进行展示提交,所以写到一个php文件中,但是完成后进行测试,当一路点击提交代码结果显示正常,但是当问卷到第三页时点击浏览器返回按钮,网页直接报错,瞬间懵逼啊!没有任何日志!代码如下: <?php if(!isset($_SESSION)) { session_start(); } $_SESSION['username'] = "zhangminchao"; $data1 = '{"paper":{&q

监听浏览器返回按钮事件

pushHistory(); window.addEventListener("popstate", function(e) { //alert("我监听到了浏览器的返回按钮事件啦");//根据自己的需求实现自己的功能 window.location = '/m/jfscapp/views/product/product_exchange.html'; }, false); function pushHistory() { var state = { title:

禁止浏览器返回按钮

浏览器的后退按钮使得我们能够方便地返回以前访问过的页面,它无疑非常有用.但有时候我们不得不关闭这个功能,以防止用户打乱预定的页面访问次序.本文介绍网络上可找到的各种禁用浏览器后退按钮方案,分析它们各自的优缺点和适用场合.    一.概述      曾经有许多人问起,“怎样才能‘禁用’浏览器的后退按钮?”,或者“怎样才能防止用户点击后退按钮返回以前浏览过的页面?”我访问了许多网站,参考了这些 网站所介绍的各种实现方法.如果你经常访问ASP编程网站,本文所介绍的部分内容你可能已经见到过.本文的任务是

IFRAME动态加载触发onload事件(转)

原文地址:http://blog.ops.cc/webtech/javascript/f5nhm.html <body> <script>var iframe = document.createElement("IFRAME"); document.body.appendChild(iframe); iframe.src = "http://www.ops.cc"; if (iframe.attachEvent) { iframe.attac

禁用浏览器器返回按钮

场景:今天在项目中遇到一种场景,需要禁用浏览器返回按钮,防止用户误操作.考虑试用一下history的新伙伴,history.pushState(),popstate事件 尝试:在各大网友的谋略中,用的最多的版本 history.pushState(null, null, document.URL);$(window).on('popstate', function() { history.pushState(null, null, document.URL);}); 果然不错,chrome和Fi

解决在点击登出之后,用户点击浏览器回退按钮能返回去继续操作问题

我在登出之后不但返回到刚才的页面.还因为我设置了拦截器而导致页面出现了我并不想看到的结果. 于是我着手对着问题进行了优化解决: 一开始我想这么做:在每张页面都有session判断,如果session为空则返回登录界面.但是就结果而言.出现了上面图片中的结果 后来我又想从前端页面着手,通过写js      window.location.href返回登录界面. 这是代码: <script type="text/javascript"> windows.location.hre

JavaScript 中 onload 事件如何绑定多个方法

页面加载完毕时会触发 onload 事件.基于内容(HTML)要与行为(JavaScript)分离的编码思想,我们需要将一些对页面的初始化操作写在方法内,并通过window.onload = functionName 调用这些方法.需要调用多个方法时,若使用 window.onload = functionA; window.onload = functionB;,它们之中只有最后一个方法会被实际调用.那么应如何实现调用多个方法呢? 直接在 HTML 中编写: <body onload="

JavaScript 中 onload 事件绑定多个方法的优化建议

页面加载完毕时会触发 onload 事件.基于内容(HTML)要与行为(JavaScript)分离的编码思想,我们需要将一些对页面的初始化操作写在方法内,并通过window.onload = functionName 调用这些方法.需要调用多个方法时,若使用 window.onload = functionA; window.onload = functionB;,它们之中只有最后一个方法会被实际调用.那么应如何实现调用多个方法呢? 直接在 HTML 中编写: <body > 由于事件包含在