浏览器返回按钮不会触发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, 分别是进入网页和离开的时候触发, 即使是用浏览器的前进/后退也会触发这两个事件.
<!DOCTYPE html> <html>
<head>
<title>Page Events</title>
<script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.7.2.js"></script>
<script>
function dispLog(msg) {
var d = new Date();
$("<li />").text(d.toISOString().substr(14, 9) + " " + msg)
.appendTo("#dvDisp"); }
$(window).load(function () {
dispLog("Load Event");
}).ready(function () {
dispLog("Ready Event");
$("#btnSetColor").click(function () {
$("a").css("color", "red");
});
}).bind("pageshow", function () {
dispLog("PageShow Event");
}).bind("pagehide", function () {
dispLog("PageHide Event");
});
</script>
</head>
<body>
<a href="test1.html">前往其它页面</a>
<input type="button" id="btnSetColor" value="变色" />
<ul id="dvDisp"></ul>
</body>
</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处理, 如下:
$.pageshow = function (fn) {
if (typeof window.onpageshow == "undefined")
$(document).ready(fn);
else
$(window).bind("pageshow", fn);
};
$.pageshow(function () {
alert("Page Show");
alert(typeof window.onpageshow == "undefined")
});
很艹蛋啊, 这个方法只能解决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
浏览器返回按钮不会触发onLoad事件的更多相关文章
- HTML5 浏览器返回按钮/手机返回按钮事件监听
1.HTML5 History对象 支持使用pushState()方法修改地址栏地址,而不刷新页面. popstate事件 当history实体被改变时,popstate事件将会发生.调用pushS ...
- event.target 属性返回哪个 DOM 元素触发了事件。
<ul> <li>list <strong>item 1</strong></li> <li><span>list ...
- JS事件 加载事件(onload)注意:1. 加载页面时,触发onload事件,事件写在<body>标签内。 2. 此节的加载页面,可理解为打开一个新页面时。
加载事件(onload) 事件会在页面加载完成后,立即发生,同时执行被调用的程序. 注意:1. 加载页面时,触发onload事件,事件写在<body>标签内. 2. 此节的加载页面,可理解 ...
- IFRAME动态加载触发onload事件(转)
原文地址:http://blog.ops.cc/webtech/javascript/f5nhm.html <body> <script>var iframe = docume ...
- jquery load()函数和window.onload事件
我想用jquery load()一个饼状图页面, 但是load不出来 代码如下: 后来百度了一下,解决办法如下: window.onload事件只有在文档载入的时候才会执行的,你载入子页面不会触发这个 ...
- GridView中的更新按钮不能触发RowUpdating事件
当点击“编辑”按钮以后,可以看到“更新”和“取消”按钮,“取消”按钮可以正常触发RowCancelingEdit事件,但是“更新”按钮不能触发RowUpdating事件. 解决方案: 在<asp ...
- onload事件,解决不能在head写代码
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta http-equiv="con ...
- JavaScript 中 onload 事件绑定多个方法的优化建议
页面加载完毕时会触发 onload 事件.基于内容(HTML)要与行为(JavaScript)分离的编码思想,我们需要将一些对页面的初始化操作写在方法内,并通过window.onload = func ...
- js onload事件使用
<!DOCTYPE html><html lang="en" xmlns="http://www.w3.org/1999/xhtml"> ...
随机推荐
- JIRA官方:JIRA定制工作流
定制适合项目的工作流 JIRA提供了一个缺省工作流和一系列问题类型,非常适合缺陷追踪和软件开发.在使用中你可以随时根据实际情况对流程进行调整,确保流程能够快速的适应坏境变化. 使你的工作流图形化 使用 ...
- HDU1879 继续畅通工程 (并查集)
继续畅通工程 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Subm ...
- Power Strings(kmp妙解)
Power Strings Time Limit : 6000/3000ms (Java/Other) Memory Limit : 131072/65536K (Java/Other) Tota ...
- .NET委托:一个关于C#的睡前故事 【转】
紧耦合 从前,在南方一块奇异的土地上,有个工人名叫彼得,他非常勤奋,对他的老板总是百依百顺.但是他的老板是个吝啬的人,从不信任别人,坚决要求随时知道彼得的工作进度,以防止他偷懒.但是彼得又不想让老板呆 ...
- IOS5开发-http get/post调用mvc4 webapi互操作(图片上传)[转]
IOS5开发-http get/post调用mvc4 webapi互操作(图片上传) 目前最流行的跨平台交互是采用http协议通过JSON对象进行互操作.这种方式最简单,也很高效.webservi ...
- InfluxDB 开源分布式时序、事件和指标数据库
InfluxDB 是一个开源分布式时序.事件和指标数据库.使用 Go 语言编写,无需外部依赖.其设计目标是实现分布式和水平伸缩扩展. 特点 schemaless(无结构),可以是任意数量的列 Scal ...
- .NET cookie 使用方法
创建 C# cookie,两种方法 Response.Cookies["userName"].Value = "patrick"; Response.Cooki ...
- DoNet开源项目-基于Amaze UI的点餐系统
帮朋友做的点餐系统,主要是为了让顾客在餐桌上,使用微信扫描二维码,就可以直接点菜,吃完使用微信付款. 系统演示地址,账户名和密码均为:admin.(请不要删除admin用户) GitHub Clone ...
- 自定义代码块移植,将Xcode中自定义的代码块导出发送到另一台mac
在终端输入 cd /users/xiefan/library/developer/xcode/userdata/codeSnippets xiefan是我的用户名,记得换成自己的用户名 进入CodeS ...
- hdu 1908
题意:一个人有一个代号K和一个优先等级P,一共有4种操作,0:结束,1:新建一个人,代号为K,优先等级为P,2:输出优先等级最大的人的代码,并删除该人,3:输出优先等级最小的人的代码,并删除该人. 用 ...