拦截浏览器后退的两种方式

在平时开发的过程中,经常会遇到类似这样的需求:用户点击后退时,弹出提示框提示用户是否退出,或者需要阻止用户后退,用户点击后退之后重定向到其他页面,这一类的需求,都需要我们能够在用户点击后退时捕获到相应的事件并进行拦截。

以下是两种拦截方式的总结:

1:利用popstate事件和pushState方法,popstate是html5新增的一个事件,它会在浏览器历史发生变化时触发,对于这个事件的描述可以见这个链接:戳我戳我,大致上可以这么理解,用户点击后退按钮时,会触发popstate事件,例如一下代码

window.addEventListener("popstate", function(){
        console.log('小敏哥很帅!!!');
    }, false);

当用户点击后退时,控制台就会打印出相应的输出,但是,光是这样还不够,因为,仅仅是捕捉到事件是无法阻止浏览器后退的,这个时候,pushState方法就派上用场了,pushState方法用于无刷新向浏览器压入一个新的记录,并把这个记录作为当前的url,具体的解释可以看后面的链接:戳我戳我,简单来说,pushState方法可以改变当前的url,并且通过第一个参数,我们能传入额外的参数信息,所以,在进入页面后等待页面初始化完成之后,我们可以通过以下的操作来对浏览器的后退事件进行拦截

//此处添加500毫秒延迟,目的是等待历史记录变化之后再添加空地址,使空地址能准确添加到栈顶,防止出错
        setTimeout(() => {
            if (!(history.state && history.state.target == "Final")) {
                window.history.pushState({target: "MeanSure", random: Math.random()}, "", "");
                window.history.pushState({target: "Final", random: Math.random()}, "", "");
            }
            window.addEventListener("popstate", function(e){
                if (e.state && e.state.target == "MeanSure") {
                    doSomething()
                }
            }, false);
        }, 500);

解释一下上线这段代码,我们进入页面之后,等待url改变完成之后我们对历史记录栈推入两个空白的页面,并且分别带入额外的信息MeanSure和Final,此时,多了两条历史记录,但是页面没有任何的改变,此时当我们点击浏览器后退时,会发现还停留在当前的页面并且触发了popstate事件,我们对比带入的target信息,如果已经后退了一个页面,当前的target信息为MeanSure,那么证明拦截成功,此时我们就可以在doSomething里面做很多事情了,比如弹提示框,或者跳转到其他的页面,或者直接history.go(1)前进一个页面,从而达到拦截后退操作的目的,这里有一个地方必须注意的,就是当你决定要取消用户的后退操作时,必须始终让用户保留在target为final的页面,不然的话下一次拦截就会失败,而当要允许用户后退时,则需要借助history.go,多后退几步,让用户回到原始页面的前一个页面,否则就会导致用户点击了几次后退没反应一脸懵逼,此处只提供一个思路,具体的实现可以随意发挥

2:其实说到这里,第二种方法很多人其实已经可以想到了,改变url不导致页面刷新,那就只有利用hashchange事件了,我们可以通过在url#号后面添加对应的标识来携带区分信息,用hashchange事件来监听后退,原理和第一个方法基本相同,就不赘述了,直接代码吧

//此处添加500毫秒延迟,目的是等待历史记录变化之后再添加空地址,使空地址能准确添加到栈顶,防止出错
        setTimeout(() => {
            if (!(location.hash && location.hash == "#Final")) {
                location.href=location.href+'#MeanSure';
                location.href=location.href+'#Final';
            }
            window.addEventListener("hashchange", function(e){
                if (location.hash && location.hash ==  "#MeanSure") {
                    doSomething()
                }
            }, false);
        }, 500);
但是利用hash来做拦截的时候有个缺点,就是url会发生变化,并且如果spa页面如果使用了前端的hash路由时,这个时候就会导致冲突,但优点在于浏览器兼容性较好,如何取舍,则要看具体的需求了

猜你喜欢

转载自blog.csdn.net/xiaomingelv/article/details/80753876