阻止浏览器返回到上一页,添加自定义操作[绝对有效]

        做前端开发的时候,可能会遇到这样的需求:当按下返回键时,添加自定义的操作,阻止浏览器返回到上一页。这样的问题,网上有一些解决方案,但是效果都不是很理想,并且还有一个重要的问题,没有把原理讲透,那么就会导致在一个场景下可能满足需求,随便换一下场景就不能保证100%阻止返回。

       

       要解决这个问题,我决定从官方的文档上入手,了解浏览器在按下返回键后底层做了哪些基础的工作。很自然的,我印象当中浏览器本身有一个关于历史的记录的管理对象,所有的历史页面都会被保存到这个对象中。

 

官方文档的解释如下:

Window.history是一个只读属性,用来获取History 对象的引用,History 对象提供了操作浏览器会话历史(浏览器地址栏中访问的页面,以及当前页面中通过框架加载的页面)的接口。

History对象有如下方法:参见 Manipulating the browser history 中的示例和详情。尤其指出的是文章里解释了在使用pushState()replaceState()方法前,你需要了解的安全问题

History对象中只有两个成员对象:

state:数组,保存着历史页面

length:历史页面的数量

注意,这里的安全问题是一个重点,接着我们在下面找到了关于安全问题的解释:

在顶层页面中,浏览器的回退和前进按钮旁的下拉菜单显示了可以通过History对象访问到的页面会话历史(session history)列表。

出于安全考虑,History对象不允许未授权代码访问会话历史(session History)中其它页面的URLs,但可以导航到其它会话历史(session History)指向的页面。

未授权代码无法清除会话历史(session History),也不能禁用回退/前进功能。最快捷的可用方式是使用location.replace()方法,提供指定的URL来替换当前的会话历史(session history)。

 

       上面的描述非常容易理解,简单说,就是浏览器的history对象出于安全的考虑,不会允许我们对历史记录做删除和修改,也不能禁用回退/前进功能。那么这样一来好像断了我们想要实现的功能,这个时候就要祭出我们的解决方案,history的pushState()方法,在官方文档中说,虽然我们不能对历史数据做删除和修改,但是我们可以通过pushState()向历史对象中添加记录,对应的还有一个popstate事件可以响应返回事件。

 

      上面说了这么多,好像一切都顺理成章,但是我有了一个疑问,既然popstate事件可以监控返回事件,为什么还要费周折通过pushState()去增加记录,不能直接通过popstate事件去监控吗?答案是肯定的,不能

 

       官方文档并没有找到对应的解释,只能自行去研究了,通过简单的调试,我发现如果不通过pushState()去增加记录,history中的state对象是null了,length记录着历史对象的数量。这个时候popstate事件不会被触发,那么通过pushState()去增加记录后,state就不为null了,很明显popstate事件的触发和state对象有关,只有state不为null时才能触发。

 

总结如下:

       浏览器出于安全考虑,history隐藏了默认的state内容,所以我们看到的是null,从而也不能对popstate事件做监控。只有我们自己手动的去通过pushState()增加记录后,state才不为null,可以对popstate事件做监控。值得一提的是每一次按下返回按钮,都会从history对象中移除一个state对象。这就是为什么有时候你会觉得popstate事件失效了,这个因为如果你只手工添加了一个state对象,那么只能响应一次popstate事件

       对于一些知识点,查询官方文档和自行分析测试才能得出正确的结果。不能一味的复制粘贴,想要提高进步,必须加入自己的思考。最后贴出完整的代码。

 <html>
<head> <meta charset="UTF-8"> </head> <body class="list"> </body> </html> <script type="text/javascript"> window.onload=function(){//初始化页面后,新增自定义的历史页面数据 pushHistory(); } window.addEventListener("popstate", function (e) { pushHistory();//若没有这行代码,第二次就会失效

//写入自定义代码//
}, false); function pushHistory() {//新增自定义的历史页面数据 var state = { title: "title", url: "#" }; window.history.pushState(state, "title", "#"); } </script>

 

posted @ 2021-01-11 10:23  colorfulCat  阅读(1495)  评论(0编辑  收藏  举报