监听物理回退与展开占满全屏

JarryChen · 2019-11-16 · 次阅读


  今天做东西,遇到一个问题,由于流程稍微有些麻烦,需要在页面之间频繁跳转。在页面上放上按钮写监听还可以,但是如果按到物理返回键呢?默认的物理返回键是返回上一页,这样子是让复杂的流程更加复杂,也无法知晓因为复杂的跳转最后会跳到哪里去,更严重点就是引发接口404的问题。

  就因为这个问题,需要更改默认的物理返回键事件。查阅了网上的资料,五花八门,也因为自己对这方面不熟悉,越搞越混乱,最后还是大家一起理顺,找到问题所在。以下是总结一下解决方法,以防以后遇到忘记了:



一. 监听物理回退

1.添加页面监听

  平时的返回只是写个方法,绑定到对应的一个组件上,路由设置好也就跳转,物理返回则不同,需要考虑几个页面之间的交互关系,一个部分搞错,后面有问题都比较难查出来

//第一步,添加监听事件,在mount里添加以下代码
mount(){
……
if ( window.history && window.history.pushState ){
    history.pushState(null, null, document.URL)    //这句话为将当前页面插入history中
    window.addEventListener('popstate',this.goTo, false) //不捕捉
}
……
}

//然后在页面销毁的周期加入去除监听
destroyed(){
    window.removeEventListener('popstate', this.goTo, false)  //这里一定要销毁,否则会出现每次按返回都触发你的自定义跳转
}

//然后是实现你自定义的跳转方法
methods{

    goTo(){
        uni.reLanch({
            url: "/pages/page/home"
        })
    },

    ……
}

2.多个页面

  注意,监听物理返回的页面,最好之间不要有直接跳转的关系,否则,很容易出现一些奇奇怪怪的问题,例如:跳转过多,history长度过长导致爆栈;或者弹窗不会弹出来。因为监听的关系很容易导致越跳越乱,如果非得要多个页面监听物理返回的跳转,可以选择跳到同一个页面,如主页……等。

  • 1.如果有弹窗,如:wx(uni).showToast、wx(uni).showModal等,两个有直接关系的页面不要都设置物理返回,否则弹窗会不出来,而你可能又会找不到问题所在。其实是两个监听互相影响了。
  • 2.既然有弹窗,就有多次按多次弹出来的问题,如果你只是confirm的时候跳转,取消的时候不作处理,同样的,按了取消第二次按返回就不会弹出弹窗。即需要在唤出弹窗的前方调用
    history.pushState(null,null,document.URL)
    然后在取消里面做你要的操作。如果将上方语句放在取消里面,则会报爆栈的错误,浏览器会变得很卡。
methods{
    goTo(){
        history.pushState(null,null,document.URL);
        uni.showModal({
            title: "提示",
            content: "是否跳回首页?",
            confirmText: "是",
            cancelText: "否",
            success: res=>{
                if(res.confirm){
                    uni.reLanch({
                        url: "/pages/page/home"
                    });
                else if(res.cancel){
                    console.log('取消')
                }
            },
            fail: err=>{
                console.log(err)
            }
       });
    }
}
//这么设置后,可防止爆栈以及可以实现点了取消之后再点能再次弹框
  • 3.除了上面两种,剩下的就是监听物理返回不回退,保持在本页,如退回到首页后,不能再让其乱回退和乱跳,只能保持在本页中,(其实应该让其关闭,只是没有很好的办法,故只能让留在本页)

    即在自定义返回的方法中加入history.pushState(null,null,document.URL)就可以了。

二. 展开占满全屏

  在网页中,更准确的是移动端中,有一种效果是点了按钮之后,展开的内容占满整个屏幕,且保持可以滑动,收缩之后又返回到页首,返回原样。这种效果虽然只是小意思,但是没接触的话来做可能也会一时摸不着头脑。坑的点主要有以下几个:

  • 展开和滚动同时作用时,什么都不生效,只展开。
  • 设置滚动到某一个容器中,不生效,网上说的滚动到某一个view,针对的是微信小程序,没有尝试过,不知道是否能用。
  • 给容器设置监听滚动到它这个地方,不生效。
  • 自己做处理,麻烦。

  然而,它坑就坑在第一点,按照逻辑是没有错的,但是一直不起作用,怀疑是自己写错,但怎么想也都是对的呀。然后,想想要不加个短短的延迟,即setTimeout()。setInterval()的话好像会引起其他问题。果然,实现了。

//写一个自定义的方法

methods{
    ……
    jumpto(e){    //这里的e是组件里传入&event这个内置参数
        this.isExpand = !this.isExpand
        if(this.isExpand){
            setTimeout(()=>{    
                uni.pageScrollto({    //页面滚动函数
                    duration: 0,    //设为0马上滚动到,大于0有一个下来的中间过程,越长越明显
                    scrollTop: e.currentTarget.offsetTop
                })
            },300)
        }
        else{
            setTimeout(()=>{    
                uni.pageScrollto({    
                    duration: 0,    
                    scrollTop: 0
                })
            },300)
        }
    },
    ……
}

  以上的问题,是在uniapp中遇到,主要还是对前端一些细节的东西没掌握好。但是啊,uniapp还是挺坑的,又要兼容小程序又要兼容h5,有的时候写着写着忘记了或者弄混了,就很容易埋雷,导致结果与自己预期不同。
  不过呀,还是要好好掌握,前端还是有挺多有意思的东西。