记一次分析、解决父页面“返回”操作导致Iframe子页面返回与实现自定义H5页面返回事件
前言:我把排查、分析思路、解决过程都记录下来了,有需要改进的地方,敬请不吝赐教。
场景:
在迎新管理系统的在线注册页面(页面包含业务模块的Iframe)进行“返回/后退”操作时,预期效果是“返回/后退”到在线注册页面的上一个页面,而实际上却是Iframe里的页面“返回/后退”了。
分析思路:
1、浏览器“返回/后退”的逻辑是什么?
浏览器“返回/后退”的逻辑一般为操作“history”对象,调用“history.back()
”或“history.go(-1)
”等方法实现“返回/后退”效果。
2、“history”对象是什么?
Window.history是一个只读属性,用来获取History 对象的引用,History 对象提供了操作浏览器会话历史(浏览器地址栏中访问的页面,以及当前页面中通过框架加载的页面)的接口。
3、Iframe子页面是否会影响父页面的“history”对象?
Iframe子页面的加载与刷新会影响父页面的“history”对象,加载与刷新记录也会记录在父页面的“history”对象内。
分析结果:
Iframe子页面的加载与刷新记录会记录在父页面的“history”对象中,而浏览器执行“返回/后退”操作时是通过操作父页面的“history”对象实现的,从而出现了在父页面进行“返回/后退”操作时,在线注册页面没有“返回/后退”到在线注册页面的上一个页面,而Iframe里的页面“返回/后退”了。
解决思路:
监听父页面的“返回/后退”操作,并通过代码“手动”返回到父页面的前一个页面。
解决方法:
1、监听父页面的“返回/后退”操作,并自定义返回事件
//以下代码放在父页面中
//该代码需要在加载此html页面一开始的地方执行(目的是要在会影响父页面history的操作前面执行,如iframe页面加载之前)
//记录父页面加载前的history长度,用于后面“手动”返回层数的计算
var initHistoryLength = history.length;
//向父页面history添加一条记录
//记录地址为“当前页面地址”+“#”,如:http://localhost:8080/cip/welcome/flow/flowMobView#
//该方法需要在加载此html页面一开始的地方执行。(目的是要在会影响父页面history的操作前面执行,如iframe页面加载之前)
//因为就算下面的代码监听到了“返回/后退”操作,但是浏览器会马上执行该操作,这时页面已经执行了“返回/后退”操作,自定义的“返回事件”已经没有意义了。所以在html页面开始加载的一开始向父页面history添加一条记录。这样的话只需要保证父页面history最后一条记录是“当前页面地址”+“#”,就算页面已经执行了“返回/后退”操作,当前页面也不会发生跳转与刷新,并且会执行自定义的“返回事件”,实现代码“手动”返回到父页面的前一个页面。
pushHistory();
//监听父页面的“返回/后退”操作
window.addEventListener("popstate", function (e) {
//自定义返回事件
//计算返回层数,并通过history.go返回到父页面的前一个页面
history.go((-1) * (history.length - initHistoryLength));
}, false);
function pushHistory() {
var state = {
title: "title",
url: "#"
};
window.history.pushState(state, "title", "#");
}
2、在所有Iframe标签中绑定“onload”事件
原因:
Iframe在加载或者刷新的时候会影响父页面的“history”记录,如果要自定义“返回事件”的正常执行就需要确保父页面history最后一条记录是“当前页面地址”+“#”。而onload
事件会在frame或者iframe载入完成后被触发,将onload
事件绑定pushHistory
函数正好可以达到这个效果。
<iframe onload="pushHistory()" src="https://www.baidu.com"></iframe>
PS:
不是所有浏览器的“返回/后退”都会触发“popstate
”事件,所以在个别执行“返回/后退”操作不触发“popstate
”事件的浏览器中自定义的“返回事件”会不生效。但经我个人测试与网上查阅的资料基本可以确定“微信内置浏览器执行返回操作后会触发popstate事件”。
参考文章:
WindowEventHandlers.onpopstate
为什么微信内置浏览器回退后100%触发popstate事件?
文章不足之处还请斧正!
本文By:NonNullPointer --2023/03/19 22:10