开发情景如下:
使用React开发移动端web app
需要监听容器元素的滚动距离来实现 实时 加载对应子元素
可滚动的容器元素非全局body
滚动方式采用原生滚动,由 css 设定 body{-webkit-overflow-scrolling:touch} 实现弹性滚动
事件监听采用过: react的onScroll事件, JQ的scroll方法及原生onscroll事件,均会出现以下问题
出现问题:
在部分浏览器(例如:safari)下,手指触发滚动后抬起,此时元素会处于弹性滚动过程,此时这部分浏览器依旧能 实时 监听到滚动事件并做出响应,另外一部分浏览器(例如:UC及微信内嵌浏览器等),当抬手让元素处于弹性滚动过程时,浏览器并不能实时进行事件响应,而是当滚动完全停止后浏览器才会执行事件回调
希望懂的朋友能帮忙解决下,万分感谢!
根据多方面的测试及咨询UC浏览器方的工程师,出现该问题的原因可以参考这个链接:
http://andyshora.com/mobile-scroll-event-problems.html
,个人不才,没有能找到好的兼容方案,下面是对自己这几天做的尝试的一个总结:原因分析:
ios的webview 内核 设定了其在进行momentum scrolling(弹性滚动)时,会停止所有的 事件响应 及 DOM操作引起的页面渲染 (亲测),故 onscroll 不能实时响应
曾做兼容方案:
使用 ontouchmove 去替代 nscroll ,虽然能更频繁的触发事件,但是这边的项目需求是实时响应滚动事件的同时,还要对页面元素进行重定位的DOM操作,由上述原因可知,在滚动过程中,页面会停止一切关于DOM方面的操作,所以若使用 ontouchmove 去实现的话,在按住屏幕进行滑动的时候,屏幕会出现元素抖动的情况(事件触发与DOM操作间具有几十毫秒的时间差),兼容失败
使用 iscroll 的probe版本,该版本能实时探查到滚动的距离,但该钩子函数是实时去关注 requestAnimationFrame 下的状态,所以对浏览器的版本性能消耗很大,加上 react 的 DOM 操作,安卓机根本动不了,兼容失败
使用 swiper 插件,在启动 freeMode 模式时模拟原生的弹性滚动( swiper 模拟原生滚动的方案能兼容较多的安卓机型不出现bug,推荐), 因为 swiper 没有实时监听滚动位置的功能,故我监听滚动开始及结束后的事件,通过 setInterval 及一些计算去实现滚动条的监听,但因为 react 元素的变化量比较大,导致 swiper 在移动端时对父容器的计算速率达到了一个瓶颈,依旧出现很卡顿的现象,兼容失败
fallback方案,安卓端使用原生onscroll实现,ios直接加载全部子元素,毕竟ios的性能方面还是比较好的,有更好的方案后续再更.