Vue 爬坑之旅 -- 解决 IOS 上滚动穿透以及由此引起的坑和爬坑过程

以前做 Android 的时候觉得 Android 适配好烦人,各种厂商,各种版本,各种机型都需要做适配,烦的一笔。现在做 H5 了,也还是要面对适配的问题,不过现在是反过来了,写好的代码在 Android 上跑的好好的,但是到了 IOS 上可能会出现各种问题,现在做适配基本都是针对 iOS 来做的了。
IOS 上要做的适配有很多,比如 1px ,图片,fixed布局,点击延迟,滚动穿透等等,各种头疼问题层出不穷。自从做了 H5 以后,我在苹果黑的路上是要越走越远了,,,

这篇文章就说下在 IOS 设备中,滚动穿透的问题怎么解决,以及要注意些什么。
首先,滚动穿透是什么,最常见的场景就是当页面上有一个对话框弹出来的时候,这时你在页面上去上下滑动,会发现对话框后面的内容会出现滚动(不论是否有半透明浮层,对话框内容是否能滚动)。
这样的表现当然不是我们所希望的,我们希望看到的是当对话框弹出时,背景页面保持不动。那么如何解决这个问题呢?针对这个问题搜索之后会发现,搜索结果很多,然而大部分要么是不能用,要么就是不知道从哪里抄过来的,看都没法看。最后,终于找到了解决办法。

解决思路就是当弹框弹出后,添加滑动事件的监听,禁止页面滑动,对话框关闭的时候再移除监听。代码如下(别人的代码。先借过来用一下,,,):

//Vue数据变量区域
data(){
/*---------监听函数--------------*/
    handler:function(e){e.preventDefault();},
...
},
//Vue函数方法区域
methods:{
    /*解决iphone页面层级相互影响滑动的问题*/
    closeTouch:function(){
        document.getElementsByTagName("body")[0].addEventListener('touchmove',
            this.handler,{passive:false});//阻止默认事件
    },
    openTouch:function(){
        document.getElementsByTagName("body")[0].removeEventListener('touchmove',
            this.handler,{passive:false});//打开默认事件
    },
    ...
}

上面代码中的二个方法,分别在对话框弹出和关闭的时候调用就行了,试了下,确实可行。然而作为一个有追求的程序猿,不能只解决了眼前的问题就结束了,要为未来多想下。

像这种弹出对话框的地方一个项目里面肯定不止一处吧,对话框基本是每个项目里面都会有吧,那么其它地方要用的话总不能把这代码到处都复制吧(话说还真有人这么干的,一段重复的代码到处复制,我现在接手的项目里面就是到处可见重复的代码,,,)。
一般这种可以可能会在多个地方用到,或者其它项目中也有可能会用到的东西,就需要把它从当前的业务代码中抽离出来,封装成公用的工具类,方便以后的开发和维护。

下面就开始这次的挖坑和爬坑过程了,,,
封装到工具类,说干就干,代码如下:

/**
   * 禁止页面滚动,解决弹框出现时 IOS 上滚动穿透的问题
   */
  forbidBodyScroll () {
    document.getElementsByTagName('body')[0].addEventListener('touchmove', function (e) {
      e.preventDefault()
    }, {passive:false})
  }
  
  /**
   * 解除禁止滚动,解决弹框出现时 IOS 上滚动穿透的问题
   */
  allowBodyScroll () {
    document.getElementsByTagName('body')[0].removeEventListener('touchmove', function (e) {
      e.preventDefault()
    }, {passive:false})
  }

封装,调用,测试,一气呵成,完美解决问题。愉快的将代码提交去测试了。此时这个问题解决了就暂时告一段落了,就去干别的事情了。
本以为这问题到此就结束了,然而并没有,过了两天,测过过来找我,说我写的一个页面有时候能滚动,有时候却不能。这是一个很简单的纯展示页面,内容是服务协议,协议内容都是直接写死的,完全没有多余的东西,怎么会不能滚动呢?
我在针对这个页面翻来覆去的各种研究,尝试后发现那问题始终存在,我花了一下午时间都没找到问题到底在哪里,真是被自己蠢哭了,实在没辙了,只有找人帮忙了。
同事过来帮忙找原因,也是找了半天没找到,后来突然说了句,你这几个页面好像都不能滚动啊,(进入协议页面之前还有二个页面,这两个页面内容很少,都不满一屏),这一说,我马上就意识到问题在哪了,对话框弹出后页面被禁止滚动了,而关闭对话框的时候页面滚动没有恢复(不能滚动的情况就是在对话框弹出之后才进入后面的页面的)。

问题原因找到就好办了,我就去查了下,添加和移除事件的相关知识, 找到一个讲的比较清楚的博客, https://blog.csdn.net/qq_29606781/article/details/67650869
看完后我就明白了,我封装的时候,添加和移除事件里面的第二个参数的那个函数要求是同一个函数,然而我封装的两个方法调用的其实是两个不同的函数,这就导致了移除滑动监听事件的时候并没有真正的移除,也就导致了后面的问题。

所以,重新封装了下,

/**
   * 禁止页面滚动和解除滚动的共用函数,具体看这个文章
   * https://blog.csdn.net/qq_29606781/article/details/67650869
   * 1:相同事件绑定和解除,需要使用共用函数;绑定和解除事件时 事件没有"on" 即onclick写成click
   * 2:共用函数不能带参数;(即下面在调用的时候是用的 this.bodyScroll,不能带()。)
   */
  bodyScroll(event){
    event.preventDefault();
  }
  
  /**
   * 禁止页面滚动,解决弹框出现时 IOS 上滚动穿透的问题
   */
  forbidBodyScroll () {
    document.getElementsByTagName('body')[0].addEventListener('touchmove', this.bodyScroll, false)
  }
  
  /**
   * 解除禁止滚动,解决弹框出现时 IOS 上滚动穿透的问题
   */
  allowBodyScroll () {
    document.getElementsByTagName('body')[0].removeEventListener('touchmove', this.bodyScroll, false)
  }

以上就是这次解决问题,以及自己挖坑和爬坑的过程,从这次的爬坑过程,也学到了一个很好的排除查找问题的方法,就是当某个问题有时候会出现,而有时候不会出现的时候,要去仔细对比这两种情况有什么不同,只有找对了方向才能找到问题的原因,不然只会白白浪费时间和精力。
将这过程记录下来,引以为戒!

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值