监控页面后退前进,浏览器文档加载事件之pageshow、pagehide
https://www.cnblogs.com/milo-wjh/p/6811868.html
http://www.runoob.com/jsref/event-onpageshow.html
onpageshow 事件
本文底部包含了更多实例。
定义和用法
onpageshow 事件在用户浏览网页时触发。
onpageshow 事件类似于 onload 事件,onload 事件在页面第一次加载时触发, onpageshow 事件在每次加载页面时触发,即 onload 事件在页面从浏览器缓存中读取时不触发。
为了查看页面是直接从服务器上载入还是从缓存中读取,你可以使用 PageTransitionEvent 对象的 persisted 属性来判断。 如果页面从浏览器的缓存中读取该属性返回 ture,否则返回 false (查看以下 "更多实例" )。
首先说说为什么会学习这个pageshow的起因吧,项目中一个表单页面,需得填写验证码,填写验证码后提交,由于使用的form直接提交,没有使用AJAX,所以,在出现验证码填写错误的时候,就会跳转到错误提示页,3秒倒计时后使用history.back(-1)的方式返回上一页,这也就出现了一个问题,使用history.back(-1)进行后退之后,图形验证码已过期,但是却没有刷新,这样就导致用户重复多次填写验证码,影响用户体验;
发现了问题,首先分析一下呗:
*浏览器前进、后退使用机制
*如何在前进、后退后执行js
一. 问题一:浏览器前进、后退使用机制
用户点击浏览器工具栏中的后退按钮,或者移动设备上的返回键时,或者JS执行history.go(-1);时,浏览器会在当前窗口“打开”历史纪录中的前一个页面。不同的浏览器在“打开”前一个页面的表现上并不统一,这和浏览器的实现以及页面本身的设置都有关系。在浏览器中,“后退到前一个页面”意味着:前一个页面的html/js/css等静态资源的请求(甚至是ajax动态接口请求)根本不会重新发送,直接使用缓存的响应,而不管这些静态资源响应的缓存策略是否被设置了禁用状态。
各个浏览器测试demo:先点击按钮使其变色,然后调整至百度,再后退回来查看:
function dispLog(msg) {
var d = new Date();
$("<li />").text(d.toISOString().substr(14, 9) + " " + msg)
.appendTo("#dvDisp");
}
window.addEventListener('load', function(event) {
dispLog("Load Event ");
})
//引入了jq监听ready事件做比较
$(window).ready(function () {
dispLog("Ready Event");
});
$("#btnSetColor").click(function () {
$("#btnSetColor").css("background", "red");
})
window.addEventListener('pageshow', function(event) {
dispLog("PageShow Event " + event.persisted);
//使用event.persisted判断页面是否使用bfcache,值为true或false; 注:如果使用jq绑定事件,需使用event.originalEvent.persisted;
})
window.addEventListener('pagehide', function(event) {
dispLog("Load Event " + event.persisted);
})
线上测试地址: pageshow
移动端测试demo:
本人的测试结果:
1.PC端浏览器
| 浏览器 | 首次进入页面 | 点击按钮,再跳转至百度,再后退 |
|---|---|---|
| chrome 58.0.3029.9 | 执行ready→load→pageshow | 重新执行ready→load→pageshow 按钮颜色消失 页面相当于重新刷新了 |
| IE789 | 执行ready→load | 重新执行ready→load 按钮颜色消失 页面相当于重新刷新了 pageshow不兼容IE10- |
| firefox 53.0.2 | 执行ready→load→pageshow | 重新执行ready→load→pageshow 按钮颜色消失 页面相当于重新刷新了 |
| QQBrowser 9.6 | 执行ready→load→pageshow | 重新执行ready→load→pageshow 按钮颜色消失 页面相当于重新刷新了 |
| 360Browser 8.1.1.254 | 执行ready→load→pageshow | 重新执行ready→load→pageshow 按钮颜色消失 页面相当于重新刷新了 |
| Safari 5.1.7(没mac,用的很早版本的windowsafari) | 执行ready→load→pageshow | 新增→pagehide→pageshow 按钮颜色红色 引用了缓存(event.persisted == true) |

PC端总结:现代的PC浏览器后退后基本都是重新执行load,对页面重新进行一次加载,所以不会有上面的验证码不刷新的问题,由于穷屌没有mac电脑,只下载了很久之前的safari浏览器,测试结果只做参考;
2.移动端浏览器 (安卓端),测试机型小米5S,iphone4s
| 浏览器 | 首次进入页面 | 点击按钮,再跳转至百度,再后退 |
|---|---|---|
| UCBrowser | 执行ready→load→pageshow | 新增→pagehide→pageshow 按钮颜色红色 引用了缓存(event.persisted == true) |
| QQBrowser | 执行ready→load→pageshow | 新增→pagehide→pageshow 按钮颜色红色 引用了缓存(event.persisted == true) |
| QQ内置浏览器 | 执行ready→load→pageshow | 重新执行ready→load→pageshow 按钮颜色消失 页面相当于重新刷新了 |
| 360Browser | 执行ready→load→pageshow | 无触发事件,按钮颜色红色 引用了缓存(event.persisted == true) |
| chorme | 执行ready→load→pageshow | 重新执行ready→load→pageshow 按钮颜色消失 页面相当于重新刷新了 |
| 微信内置 | 执行ready→load→pageshow | 重新执行ready→load→pageshow 按钮颜色消失 页面相当于重新刷新了 |
| 小米自带 | 执行ready→load→pageshow | 无触发事件,按钮颜色红色 引用了缓存(event.persisted == true) |
| safari | 执行ready→load→pageshow | 新增→pagehide→pageshow 按钮颜色红色 引用了缓存(event.persisted == true) |
效果图:选了三种类型各一个
| 刷新页面类型 | 不刷新不执行类型 |
|---|---|
![]() |
![]() |
| 不刷新执行事件类型(理想型) |
|---|
![]() |
这就很头疼了,三种不同的情况,对于chrome和UC类型的情况,对于我的回退验证码刷新问题,很容易处理,最麻烦的360类型的,但是。。。发现了更蛋疼的情况了:
后退不reload,不执行pageshow的浏览器在公司的一个项目中,居然能实现后退刷新。。。。 同一段测试代码,发到项目服务器上,是可以后退刷新,
但是,在我自己的虚拟主机中却不行,南蝶?是因为请求头部设置吗??? 先挖个坑在这,等我去好好了解一下PHP 和 http请求 再回来战!
二、如何在前进、后退后执行js
百度、google类似问题,最多的解决方法:pageshow;
Firefox和Opera有一个新特性,名叫“往返缓存”(back-forward cache,或bfcache),可以在用户使用浏览器的“后退”和“前进”按钮时加快页面的转换速度。
这个缓存中不仅保存着页面数据,还保存了DOM和JavaScript的状态;实际上是将整个页面都保存在了内存里。
如果页面位于bfcache中,那么再次打开该页面就不会触发load事件。
尽管由于内存中保存了整个页面的状态,不触发load事件也不应该会导致什么问题,但为了更形象地说明bfcache的行为,Firefox还是提供了一些新事件。
第一个事件就是pageshow,这个事件在页面显示时触发,无论页面是否来自bfcache。在重新加载页面中,pageshow会在load事件触发后触发;
而对于bfcache中的页面,pageshow会在页面状态完全恢复的那一刻触发。另外要注意的是,虽然这个事件的目标是document,但必须将其事件处理程序添加到window。
监控页面后退前进,浏览器文档加载事件之pageshow、pagehide的更多相关文章
- jQuery文档加载事件
$(document).ready(handler) $().ready(handler) (this is not recommended) $(handler) 相当于: $(document). ...
- 原生JS与jQuery文档加载完毕的写法
HTML是有执行顺序的,默认是自上而下执行.所以当我们的js代码在html代码下边的时候,可以正常执行,而当我们的js代码在html代码上边的时候,可以就无法正常执行了,这时,我们需要在文档加载完毕的 ...
- js坚持不懈之14:不要在文档加载之后使用 document.write()示例
在看w3school的JavaScript教程时,关于文档输出流中有这么一句话:绝不要在文档加载之后使用 document.write().这会覆盖该文档. 不太明白什么意思,找了一个例子: < ...
- document.write : 什么是在html输出中使用,什么是文档加载后使用?
理解:您只能在 HTML 输出中使用 document.write.如果您在文档加载后使用该方法,会覆盖整个文档. Javascript中只能在 HTML 输出流中使用 document.write, ...
- 基于DOMContentLoaded实现文档加载完成后执行的方法
我们有时可能需要一些在页面加载完成之后执行的方法,其实js原生就提供了onload方法,所以我们最简单的办法就是直接给onload赋值一个函数,在页面加载完成之后就会自动执行 widnow.onloa ...
- VS2010 release编译下进行调试,“当前不会命中任何断点,还没有为文档加载”问题解决方案
在release模式下调试程序,经常出现"当前不会命中任何断点,还没有为文档加载"的问题,可尝试以下方法: 1. 属性 → 配置属性 → C/C++ → 常规 → 调试信息格式:选 ...
- Javascript绝不要使用在文档加载之后使用 document.write(), 怎么理解?
在文档加载之后使用 document.write(),会覆盖该文档. 需满足两个条件: 1.在函数内部调用document.write(): 2.通过按钮响应调用函数: 举 ...
- jQuery文档加载完毕的几种写法
js中文档加载完毕.一般在body加一个onload事件或者window.onload = function () {} jQuery中有好多写法,平时也不注意,别人一问,还真觉得头大. 下面是我整理 ...
- release环境下,当前不会命中断点,还没有为该文档加载任何符号
今天在release编译环境下出现了如标题所说的问题“ 当前不会命中断点,还没有为该文档加载任何符号”,在网上找了几个方法都没有解决我的问题,咨询了一下师傅,解决了,很简单,方法如下:右键--属性-- ...
随机推荐
- Daily record-June
June201. Dear, wake up! Seven o'clock now, it's time to get up. Wash your face and to have breakfast ...
- learning ddr tRP and tRP tRTP CL tRAS
referce :https://blog.csdn.net/ghostyu/article/details/7728106 tRP(RAS Precharge Time): “内存行地址控制器预充电 ...
- js 中class选择器,addClass,removeClass,hasClass,toggleClass,getByClass
<!doctype html> <html> <head> <meta charset="utf-8"> <meta name ...
- 深入研究sqlalchemy连接池
简介: 相对于最新的MySQL5.6,MariaDB在性能.功能.管理.NoSQL扩展方面包含了更丰富的特性.比如微秒的支持.线程池.子查询优化.组提交.进度报告等. 本文就主要探索MariaDB当中 ...
- 读书笔记 C# 接口之浅析
一.接口可以包含 属性.方法.事件和索引器: 二.接口不能被实例化: 三.一个类可以继承多个接口: 四.接口不能包含方法的实现: 五.继承接口的类必须实现接口中所有成员: 六.显式实现接口的成员,不能 ...
- C++各种类继承关系的内存布局
body, table{font-family: 微软雅黑; font-size: 10pt} table{border-collapse: collapse; border: solid gray; ...
- 7.7 C++基本关联式容器
参考:http://www.weixueyuan.net/view/6404.html 总结: 基本的关联式容器主要有:set.multiset.map和multimap,这四种容器可以分为两组:ma ...
- SQL-8 找出所有员工当前(to_date='9999-01-01')具体的薪水salary情况,对于相同的薪水只显示一次,并按照逆序显示
题目描述 找出所有员工当前(to_date='9999-01-01')具体的薪水salary情况,对于相同的薪水只显示一次,并按照逆序显示CREATE TABLE `salaries` (`emp_n ...
- Linux文件系统命令 umask
命令:umask 功能:指定创建文件或者文件夹的时,默认的权限设置 用法:umask -S:以rwx的方式查看创建文件的权限 umask -p:以补位的方式查看文件的权限,显示的是补位的十进制. 另外 ...
- el-container 实践上的布局问题
当自己利用element-ui上面的例子来实现整体布局的时候, 就是自己分开成单独的vue组件时,发现布局是不对的,效果是这样的: 代码是这样的,代码一模一样,只是拆开了各个组件,如下图: 后来发现是 ...
事件对象

