2

【场景】

相信大家用安卓手机使用APP的过程中,会遇到这样的一个场景:按下手机的返回键时,会弹出一个询问框:"是否退出该页面/APP?",然后点击了确认键才真正退出APP。PC端目前可以通过页面的转场实现。那这样的效果在H5/微信浏览器/移动端浏览器,能否实现呢?

ps:现在好像很少看到弹出框了,而是弹出一个toast,然后需要在有效时间内再次点击才算退出。这个功能其实应该也可以实现。

【主要需求】

1.安卓手机用户按下返回键不后退网页。弹出询问框

2.当用户点击“确定”按钮,才算后退

【思路】

以上的需求,按我的理解就是一句话:“监听安卓手机返回键”,通过百度/google,虽然发现此功能仍没有很好的解决方案,但是看到了两个与此相关的线索: history pushSate/replaceSateonpopstate 。 大家也可以看看张鑫旭大神的文章:传送门

这两个API的作用简单来说就是前者可以在浏览器地址栏上添加/替换一条记录,当浏览器发生后退动作时,触发后者api.

(function(){
                if(window.location.hash==""){
                history.pushState(null,null,"#1")//一访问页面即添加一条记录b.html -> b.html#1
            }
            window.onpopstate = function(event) {//当用户按下返回键,b.html#1 -> b.html,并触发该事件
                if(confirm("确定要退出吗")){
                    history.back()   //执行真正的退出
                }else{
                  history.pushState(null,null,"#1") //用户取消,恢复   b.html -> b.html#1
                }
           };
        }    
        )();

【改进】

一切看上去很美好,看似把功能实现了,但是,细心的用户就会发现,当按下返回键,弹出询问框时,我们既不按确认,也不按取消,直接再次按下返回键,页面仍然跳转。因此我们需要改进代码。

    (function(){
            if(window.location.hash==""){
                history.pushState(null,null,"#1")//一访问页面即添加一条记录b.html -> b.html#1
            }
            
            window.onpopstate = function(event) {//当用户按下返回键,b.html#1 -> b.html,并触发该事件
                history.pushState(null,null,"#1")
                if(confirm("确定要退出吗")){
                    history.go(-2)   //执行真正的退出
                }else{
                                 //用户取消,恢复   b.html -> b.html#1
                }
           };
        }    
        )();

如上,我们每次的后退,都假定用户都按了取消键,这样问题就解决了。

测试后没问题。但这仍然不是完美的方案,例如在微信浏览器,confirm的次数一旦超过三次,就要强制退出,无法取消,或者通常我们开发时都用到第三方的UI库的弹框而不用原生的弹框.....所以下面给出了用mui的框架实现以上功能。

  if (window.location.hash == "") {
        history.pushState("change", '', "#pageone");
        state = "change"
    } 

    window.onpopstate = function (e) {
      

            if (state == "confirm") {
                history.pushState("change", '', "#pageone");
                state = "change";
                mui.closePopup();
                return;
            }
            history.pushState("confirm", '', "#pageone");
            state = "confirm";
            mui.confirm("是否退出编辑?", "", ["否", "是"], function (e) {
                if (e.index == 0) {
                    history.replaceState("change", '', "#pageone");
                    state = "change";
                 
                }
                else {
                    history.go(-2)
                }

            }, "div");
       
         }
        

【总结】

由于此api的兼容性极其低,因此不建议大家广泛使用,学习交流还是可以的哈哈,针对监听返回键,大家有更好的解决方案,也可以分享一下。


Hing
5 声望0 粉丝