记IOS下UIWebView的坑

ios在uiwebview下的坑

最近作了一个需求,须要作吸顶的效果,在安卓机器和IOS高版本系统下,能改完美实现吸顶效果,可是在低版本的IOS中,却遇到了坑,当我滚动到吸顶的位置的时候,它仍然没有吸顶,只有滚动中止的时候才吸顶。
vue

image

google分析了缘由,有两种缘由会致使这种状况。react

一、uiwebview下scroll事件只会在滚动中止时触发

若是你监听滚动是使用addEventListener的方式,那么很遗憾的告诉你,你中招了,经过这种方式绑定滚动事件,如标题所示,只会在滚动中止的时候才触发一次,相似防抖操做,只有在最后一次触发。ios

可是,若是你用window.onscroll的方式监听滚动的话,就能够在滚动的过程当中触发scroll事件了,是否是很神奇?web

网上还有说用touchmove来监听,也是能够在滚动的时候触发事件的,可是touchmove有两个缺点是:bash

  • 它触发频率低,就是须要滚动必定的距离才会触发
  • 它会惯性滚动,即咱们手指离开的时候,它还会模拟惯性滚动一段距离,而这个时候,无论是scroll仍是touchmove都没法触发。

然而,我改成onscroll监听滚动了,但是我仍是没法及时更新吸顶元素,仍是和用addEventListener来监听scroll的效果同样,在滚动中止的时候才会吸顶。这就要导出第二个会致使这个现象的缘由了。框架

二、uiwebview下,scroll里面的全部异步操做都会被阻塞

会出现这个的缘由,估计和第一个缘由同样,IOS想要作一些优化,避免一些重复的操做,就和咱们作函数节流同样的思想,可是出这个方案的大神,你就没想到这样一刀切的方式会让咱们开发者遇到不少坑吗(借机吐槽下)?个人技术栈是用vue,而咱们知道,vue是异步更新dom的,因此我在onscroll里面经过vue更新视图的操做,都会被ios阻塞,只有滚动中止后才会拿出来执行。dom

顺便说一句,若是你的滚动处理函数使用防抖来优化,那效果仍是同样,由于防抖的实现原理是setTimeout,而setTimeout也是异步操做,都会被IOS阻塞。异步

解决方案

具体看你们的状况,若是是第一种缘由致使的,请使用window.onscroll来监听滚动,若是是第二种缘由,请避免在scroll事件中使用异步操做,而若是你是使用vue或者react这些框架,它们都会异步去更新dom。函数

方案一

根据是不是uiwebview,选择性地使用正常的方式和原生js操做dom更新视图优化

if (isUIWebView) {
    window.onscroll = function() {
        // 使用原生js操做dom
    }
} else {
    // 正常的状况,使用防抖、vue|react去操做dom
    window.addEventListener('scroll', this.scrollHandler)
}
复制代码

方案二

使用第三方滚动插件模拟滚动,好比iscroll之类的。

其余坑

  • os元素设置inline-block后元素下沉的问题

由于display: inline-block成了内联,inline box有一个叫作baseline的东西,若是有的元素有多行文字,有的只有一行,就会以baseline为基准,想要更改很简单只要vertical-align: top;和vertical-align: bottom;

  • 在ios的uiwebview下,pageYOffset属性是无效的
    献上获取滚动距离的兼容性写法
function getScrollTop(el) {
  if (!el) {
    return document.documentElement.scrollTop || window.pageYOffset || document.body.scrollTop;
  }
  return el.scrollTop;
}
复制代码
相关文章
相关标签/搜索