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)

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。

 
分类: JS相关

监控页面后退前进,浏览器文档加载事件之pageshow、pagehide的更多相关文章

  1. jQuery文档加载事件

    $(document).ready(handler) $().ready(handler) (this is not recommended) $(handler) 相当于: $(document). ...

  2. 原生JS与jQuery文档加载完毕的写法

    HTML是有执行顺序的,默认是自上而下执行.所以当我们的js代码在html代码下边的时候,可以正常执行,而当我们的js代码在html代码上边的时候,可以就无法正常执行了,这时,我们需要在文档加载完毕的 ...

  3. js坚持不懈之14:不要在文档加载之后使用 document.write()示例

    在看w3school的JavaScript教程时,关于文档输出流中有这么一句话:绝不要在文档加载之后使用 document.write().这会覆盖该文档. 不太明白什么意思,找了一个例子: < ...

  4. document.write : 什么是在html输出中使用,什么是文档加载后使用?

    理解:您只能在 HTML 输出中使用 document.write.如果您在文档加载后使用该方法,会覆盖整个文档. Javascript中只能在 HTML 输出流中使用 document.write, ...

  5. 基于DOMContentLoaded实现文档加载完成后执行的方法

    我们有时可能需要一些在页面加载完成之后执行的方法,其实js原生就提供了onload方法,所以我们最简单的办法就是直接给onload赋值一个函数,在页面加载完成之后就会自动执行 widnow.onloa ...

  6. VS2010 release编译下进行调试,“当前不会命中任何断点,还没有为文档加载”问题解决方案

    在release模式下调试程序,经常出现"当前不会命中任何断点,还没有为文档加载"的问题,可尝试以下方法: 1. 属性 → 配置属性 → C/C++ → 常规 → 调试信息格式:选 ...

  7. Javascript绝不要使用在文档加载之后使用 document.write(), 怎么理解?

    在文档加载之后使用 document.write(),会覆盖该文档.   需满足两个条件:      1.在函数内部调用document.write():      2.通过按钮响应调用函数:   举 ...

  8. jQuery文档加载完毕的几种写法

    js中文档加载完毕.一般在body加一个onload事件或者window.onload = function () {} jQuery中有好多写法,平时也不注意,别人一问,还真觉得头大. 下面是我整理 ...

  9. release环境下,当前不会命中断点,还没有为该文档加载任何符号

    今天在release编译环境下出现了如标题所说的问题“ 当前不会命中断点,还没有为该文档加载任何符号”,在网上找了几个方法都没有解决我的问题,咨询了一下师傅,解决了,很简单,方法如下:右键--属性-- ...

随机推荐

  1. Daily record-June

    June201. Dear, wake up! Seven o'clock now, it's time to get up. Wash your face and to have breakfast ...

  2. learning ddr tRP and tRP tRTP CL tRAS

    referce :https://blog.csdn.net/ghostyu/article/details/7728106 tRP(RAS Precharge Time): “内存行地址控制器预充电 ...

  3. js 中class选择器,addClass,removeClass,hasClass,toggleClass,getByClass

    <!doctype html> <html> <head> <meta charset="utf-8"> <meta name ...

  4. 深入研究sqlalchemy连接池

    简介: 相对于最新的MySQL5.6,MariaDB在性能.功能.管理.NoSQL扩展方面包含了更丰富的特性.比如微秒的支持.线程池.子查询优化.组提交.进度报告等. 本文就主要探索MariaDB当中 ...

  5. 读书笔记 C# 接口之浅析

    一.接口可以包含 属性.方法.事件和索引器: 二.接口不能被实例化: 三.一个类可以继承多个接口: 四.接口不能包含方法的实现: 五.继承接口的类必须实现接口中所有成员: 六.显式实现接口的成员,不能 ...

  6. C++各种类继承关系的内存布局

    body, table{font-family: 微软雅黑; font-size: 10pt} table{border-collapse: collapse; border: solid gray; ...

  7. 7.7 C++基本关联式容器

    参考:http://www.weixueyuan.net/view/6404.html 总结: 基本的关联式容器主要有:set.multiset.map和multimap,这四种容器可以分为两组:ma ...

  8. SQL-8 找出所有员工当前(to_date='9999-01-01')具体的薪水salary情况,对于相同的薪水只显示一次,并按照逆序显示

    题目描述 找出所有员工当前(to_date='9999-01-01')具体的薪水salary情况,对于相同的薪水只显示一次,并按照逆序显示CREATE TABLE `salaries` (`emp_n ...

  9. Linux文件系统命令 umask

    命令:umask 功能:指定创建文件或者文件夹的时,默认的权限设置 用法:umask -S:以rwx的方式查看创建文件的权限 umask -p:以补位的方式查看文件的权限,显示的是补位的十进制. 另外 ...

  10. el-container 实践上的布局问题

    当自己利用element-ui上面的例子来实现整体布局的时候, 就是自己分开成单独的vue组件时,发现布局是不对的,效果是这样的: 代码是这样的,代码一模一样,只是拆开了各个组件,如下图: 后来发现是 ...