在平时开发的过程中,经常会遇到类似这样的需求:用户点击后退时,弹出提示框提示用户是否退出,或者需要阻止用户后退,用户点击后退之后重定向到其他页面,这一类的需求,都需要我们能够在用户点击后退时捕获到相应的事件并进行拦截。
以下是两种拦截方式的总结:
1:利用popstate事件和pushState方法,popstate是html5新增的一个事件,它会在浏览器历史发生变化时触发,对于这个事件的描述可以见这个链接:戳我戳我,大致上可以这么理解,用户点击后退按钮时,会触发popstate事件,例如一下代码
("popstate", function(){
('小敏哥很帅!!!');
}, false);
当用户点击后退时,控制台就会打印出相应的输出,但是,光是这样还不够,因为,仅仅是捕捉到事件是无法阻止浏览器后退的,这个时候,pushState方法就派上用场了,pushState方法用于无刷新向浏览器压入一个新的记录,并把这个记录作为当前的url,具体的解释可以看后面的链接:戳我戳我,简单来说,pushState方法可以改变当前的url,并且通过第一个参数,我们能传入额外的参数信息,所以,在进入页面后等待页面初始化完成之后,我们可以通过调用以下的doIt()方法来对浏览器的后退事件进行拦截
//封装的常规操作,跳转到其他页面
function toUrl(url){
//首先跳回顶点,防止多次添加记录
({target: "Final",}, "", );
=url;
}
//封装的常规操作,回退到上一级
function back() {
let backCount= == "Final"?-3:-2;
(backCount);
}
//封装的常规操作,停留在本页面
function stay() {
();
}
//实际的拦截操作
function doIt() {
//此处添加500毫秒延迟,目的是等待历史记录变化之后再添加空地址,使空地址能准确添加到栈顶,防止出错
setTimeout(() => {
if (!( && == "Final")) {
({target: "MeanSure", random: ()}, "", );
({target: "Final", random: ()}, "", );
}
("popstate", function (e) {
if ( && == "MeanSure") {
//此处可调用一些自定义的操作,例如弹窗提示之类的,最后根据实际需要可调用上面三个函数中的任何一个,用于决定当前自定义操作完成之后,需要停留在本页面,还是回退,还是跳转到其他页面
doSomething();
//stay();如此操作会停留在本页面
//back();如此操作会无副作用回退到上一级
//toUrl('');如此操作会执行完之定义操作之后跳转到百度
}
}, false);
}, 500);
}
解释一下上线这段代码,我们进入页面之后,等待url改变完成之后我们对历史记录栈推入两个和当前页面一模一样的页面,并且分别带入额外的信息MeanSure和Final,此时,多了两条历史记录,但是页面没有任何的改变,此时当我们点击浏览器后退时,会发现还停留在当前的页面并且触发了popstate事件,我们对比带入的target信息,如果已经后退了一个页面,当前的target信息为MeanSure,那么证明拦截成功,此时我们就可以在doSomething里面做很多事情了,比如弹提示框,或者跳转到其他的页面,或者直接(1)前进一个页面,从而达到拦截后退操作的目的,这里有一个地方必须注意的,就是当你决定要取消用户的后退操作时,必须始终让用户保留在target为final的页面,不然的话下一次拦截就会失败,而当要允许用户后退时,则需要借助,多后退几步,让用户回到原始页面的前一个页面,否则就会导致用户点击了几次后退没反应一脸懵逼,此处只提供一个思路,具体的实现可以随意发挥
2:其实说到这里,第二种方法很多人其实已经可以想到了,改变url不导致页面刷新,那就只有利用hashchange事件了,我们可以通过在url#号后面添加对应的标识来携带区分信息,用hashchange事件来监听后退,原理和第一个方法基本相同,就不赘述了,直接代码吧
//实际的拦截操作
function doIt() {
//此处添加500毫秒延迟,目的是等待历史记录变化之后再添加空地址,使空地址能准确添加到栈顶,防止出错
setTimeout(() => {
if (!( && == "#Final")) {
=+'#MeanSure';
=+'#Final';
}
("hashchange", function(e){
if ( && == "#MeanSure") {
doSomething();
}
}, false);
}, 500);
}
但是利用hash来做拦截的时候有个缺点,就是url会发生变化,并且如果spa页面如果使用了前端的hash路由时,这个时候就会导致冲突,但优点在于浏览器兼容性较好,如何取舍,则要看具体的需求了