Vue 爬坑之旅 -- 解决 IOS 上滚动穿透以及由此引起的坑和爬坑过程
以前做 Android 的时候觉得 Android 适配好烦人,各种厂商,各种版本,各种机型都需要做适配,烦的一笔。现在做 H5 了,也还是要面对适配的问题,不过现在是反过来了,写好的代码在 Android 上跑的好好的,但是到了 IOS 上可能会出现各种问题,现在做适配基本都是针对 iOS 来做的了。IOS 上要做的适配有很多,比如 1px ,图片,fixed布局,点击延迟,滚动穿透等等,各种.
以前做 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)
}
以上就是这次解决问题,以及自己挖坑和爬坑的过程,从这次的爬坑过程,也学到了一个很好的排除查找问题的方法,就是当某个问题有时候会出现,而有时候不会出现的时候,要去仔细对比这两种情况有什么不同,只有找对了方向才能找到问题的原因,不然只会白白浪费时间和精力。
将这过程记录下来,引以为戒!
更多推荐
所有评论(0)