前端: 移动端onscroll事件在部分浏览器内不能实时触发

ahmu
  • 88

开发情景如下:

  • 使用React开发移动端web app

  • 需要监听容器元素的滚动距离来实现 实时 加载对应子元素

  • 可滚动的容器元素非全局body

  • 滚动方式采用原生滚动,由 css 设定 body{-webkit-overflow-scrolling:touch} 实现弹性滚动

  • 事件监听采用过: react的onScroll事件, JQ的scroll方法及原生onscroll事件,均会出现以下问题

出现问题:

  • 在部分浏览器(例如:safari)下,手指触发滚动后抬起,此时元素会处于弹性滚动过程,此时这部分浏览器依旧能 实时 监听到滚动事件并做出响应,另外一部分浏览器(例如:UC及微信内嵌浏览器等),当抬手让元素处于弹性滚动过程时,浏览器并不能实时进行事件响应,而是当滚动完全停止后浏览器才会执行事件回调

希望懂的朋友能帮忙解决下,万分感谢!

回复
阅读 36.4k
6 个回答
✓ 已被采纳

根据多方面的测试及咨询UC浏览器方的工程师,出现该问题的原因可以参考这个链接:http://andyshora.com/mobile-scroll-event-problems.html,个人不才,没有能找到好的兼容方案,下面是对自己这几天做的尝试的一个总结:

原因分析:

  • ios的webview 内核 设定了其在进行momentum scrolling(弹性滚动)时,会停止所有的 事件响应DOM操作引起的页面渲染 (亲测),故 onscroll 不能实时响应

曾做兼容方案:

  1. 使用 ontouchmove 去替代 nscroll ,虽然能更频繁的触发事件,但是这边的项目需求是实时响应滚动事件的同时,还要对页面元素进行重定位的DOM操作,由上述原因可知,在滚动过程中,页面会停止一切关于DOM方面的操作,所以若使用 ontouchmove 去实现的话,在按住屏幕进行滑动的时候,屏幕会出现元素抖动的情况(事件触发与DOM操作间具有几十毫秒的时间差),兼容失败

  2. 使用 iscroll 的probe版本,该版本能实时探查到滚动的距离,但该钩子函数是实时去关注 requestAnimationFrame 下的状态,所以对浏览器的版本性能消耗很大,加上 react 的 DOM 操作,安卓机根本动不了,兼容失败

  3. 使用 swiper 插件,在启动 freeMode 模式时模拟原生的弹性滚动( swiper 模拟原生滚动的方案能兼容较多的安卓机型不出现bug,推荐), 因为 swiper 没有实时监听滚动位置的功能,故我监听滚动开始及结束后的事件,通过 setInterval 及一些计算去实现滚动条的监听,但因为 react 元素的变化量比较大,导致 swiper 在移动端时对父容器的计算速率达到了一个瓶颈,依旧出现很卡顿的现象,兼容失败

  4. fallback方案,安卓端使用原生onscroll实现,ios直接加载全部子元素,毕竟ios的性能方面还是比较好的,有更好的方案后续再更.

该回答如有错误,望请各位多多指正.

车仔面
  • 2
新手上路,请多包涵

也是遇到这个问题 ..移动端不用考虑兼容ie的话 css3 有个新属性可以用,position:sticky就可以完美解决~

Phin
  • 3
新手上路,请多包涵

手机京东的顶部 搜索条 就可以实时监听scroll 实现滚动变色

eeandrew
  • 1
新手上路,请多包涵

这个没有办法,移动端浏览器内核限制了onscroll事件的触发频率。需要用iScroll.js。本质其实就是自己实现滚动。

监听body 的scroll 事件来代替window.onscroll。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
你知道吗?

宣传栏