vue结合preventDefault()和页面滚动高度计算,解决ios橡皮筋效果

发布时间:2019-06-30 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了vue结合preventDefault()和页面滚动高度计算,解决ios橡皮筋效果脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。
    感谢<https://www.cnblogs.COM/cuncunjun/p/7493782.htML>的启发,方法很有用!
    好几个月以前,我写了一个类似于自动回复那种的客服页面,嵌入到公司开发的app里。上周测试突然找到我,说
页面在滑动的时候,输入框也会跟着上下滑动,而这个问题只在ios系统上出现,Android没问题。测试的同学希望我
做点什么,把页面固定住,不要随着手指的滑动上下动。修改前的界面大概像下面的示意图这样:   

向上拉动页面向下拉动页面

    经过百度知道了这叫做橡皮筋效果,是ios系统在引入网页时专有的一种效果.要去掉这种效果,可以采用fixed
布局,也可以监听touchmove事件,利用event.preventDefault()解决。第一种方法我尝试了,觉得不是很好用,而
且页面的滑动变得卡顿,橡皮筋效果还是时而出现,因此考虑第二种办法。
    event.PReventDefault()说白了就是监听touchmove,在手指滑动屏幕的时候,禁止掉页面随手指滑动而滚动的
默认事件。看到这里问题就来了,我的页面是一个聊天页面,聊天记录还是可以通过上下滑动手指来查看的,如果禁止
了滚动页面,岂不是动不了了?
    所以,需要给preventDefault()增加一个限制条件,即只有页面滑动到顶部或者底部了,才调用preventDefault(),
阻止对应的滑动事件。那么,如何判断页面是否已经滑动到两端呢?利用clientHeight、scrollHeight和scrollTop
三个属性。
    我们对这三个属性做一下区分(对页面中同一个元素而言):
        clientHeight是元素展示在页面中的固定高度;
        scrollHeight是当元素中内容很多,出现滚动条时,元素中内容的实际高度,scrollHeight>=clientHeight,
    当不需要滚动页面时,二者相等;
        scrollTop是当页面滚动时,页面中内容向上卷起来的距离,即内容的顶部距离固定的元素顶部的距离。

图片描述

    由上面的定义可知,当页面滑动到顶部时,scrollTop为0,当页面出现橡皮筋时,scrollTop小于0.当页面滑动
到底部时,scrollTop + clientHeight = scrollHeight。因此,我们可以写下这样的代码:
mounted(){
//判断是不是ios
      let u = navigator.userAgent;
      let isiOS = !!u.match(/(i[^;]+;( U;)? CPU.+Mac OS X/); //ios终端

      //如果是ios,执行下面的代码
      if(isiOS){
      //因为要禁止整个页面的滑动,所以定义一个box,里面装有chatBody和foot两个子元素
        const box = document.getElementById("longbox");  
        const chatBody = document.getElementById("chatContainer");
        //开始滑动,此处使用box元素的事件监听,来禁止整个页面的滑动
        box.addEventListener("touchmove", function(e){
            //如果滑到顶端或底端,禁止滑动
          if(chatBody.scrollTop<=0 || chatBody.scrollTop + chatBody.clientHeight>=chatBody.scrollHeight){
            e.preventDefault();
          }
        })
      }
  }
    测试一下,发现一个问题,的确当滑动到顶部时,无法继续上滑了,但同时也无法下滑了。为什么?因为@H_930_126@e.preventDefault()组织的是所有方向上的滑动事件,所以当页面滑到顶端或者底端时,禁止了一切的滑动,页面就动不了了。因此,考虑改进代码,增加一个上滑或者下滑的判断:
mounted(){
//判断是不是ios
      let u = navigator.userAgent;
      let isiOS = !!u.match(/(i[^;]+;( U;)? CPU.+Mac OS X/); //ios终端

      //如果是ios,执行下面的代码
      if(isiOS){
      //因为要禁止整个页面的滑动,所以定义一个box,里面装有chatBody和foot两个子元素
        const box = document.getElementById("longbox");
        const chatBody = document.getElementById("chatContainer");
        VAR startY,endY; //定义滑动的起点和终点
        //监听touchstart事件,记录滑动起点的位置
        box.addEventListener("touchstart", function(e){
          startY = e.touches[0].pageY;
        })
        //开始滑动,此处使用box元素的事件监听,来禁止整个页面的滑动
        box.addEventListener("touchmove", function(e){
          endY = e.touches[0].pageY;  //记录此时的滑动y轴坐标
         
          //页面向上滑动
          //页面滚动上去的长度scrollTop
          if(endY>startY&amp;& chatBody.scrollTop<=0){
            e.preventDefault();
          }

          //页面向下滑动
          //页面的总长度(包括滚动上去的部分)scrollHeight
          if(endY<startY&& chatBody.scrollTop + chatBody.clientHeight>=chatBody.scrollHeight){
            e.preventDefault();
          }
        })
      }
  }
   再测试,解决橡皮筋效果~
   啰嗦一下,上面的代码是最终解决版的代码,但其实中间还是遇到了一个小坑的,就是在多层div嵌套时,父容器的
   高度可能不定,由子容器撑开。比如我这个聊天页面,父容器box只标注了height:100%; container包括两个子容
   器:子容器chat是需要滑动的div,不定高,还有一个高度为47px的foot子容器。这时候,需要禁止整个页面(其
   实就是父容器)的滑动,子容器chat可以滑动,所以,要监听box的事件,禁止的也是box的滑动,而是否滑动到页
   面顶端/底端的判断依据,则需要对chat的scrollHeight和scrollTop进行判断。
   第一次写文章,说的不对的地方,还请多多指正!

脚本宝典总结

以上是脚本宝典为你收集整理的vue结合preventDefault()和页面滚动高度计算,解决ios橡皮筋效果全部内容,希望文章能够帮你解决vue结合preventDefault()和页面滚动高度计算,解决ios橡皮筋效果所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。