监控页面后退前进,浏览器文档加载事件之pageshow、pagehide

https://www.cnblogs.com/milo-wjh/p/6811868.html

http://www.runoob.com/jsref/event-onpageshow.html

onpageshow 事件

事件对象参考手册 事件对象

实例

在用户浏览网页时触发 JavaScript:

<body onpageshow="myFunction()">

尝试一下 »

本文底部包含了更多实例。


定义和用法

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)

safari

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测试页面效果
不刷新执行事件类型(理想型)
这就很头疼了,三种不同的情况,对于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。

 
分类:  JS相关

首先说说为什么会学习这个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)

safari

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测试页面效果
不刷新执行事件类型(理想型)
这就很头疼了,三种不同的情况,对于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。

猜你喜欢

转载自www.cnblogs.com/linus-tan/p/10142386.html
今日推荐