您的位置:首页 > 其它

惯性滚动及引发的问题整理

2017-11-06 16:32 218 查看
文章部分内容引自http://www.cnblogs.com/chris-oil/p/6164966.html

前文说到,在iOS上滚动事件不顺滑,有个解决方案是使用-webkit-overflow-scrolling 属性。

简介:-webkit-overflow-scrolling 

一个只有 iOS 设备支持的非标准属性。苹果自己的解释:指定是否在 overflow: scroll 的元素中使用“原生”的滚动方式

包含两个可选值:auto 和 touch

auto:就是普通的无惯性滚动效果

touch:原生的滚动效果。使用此效果会构造一个 stacking context

什么是 stacking context?可以参照这里的解释

-webkit-overflow-scrolling 引发了那些坑?

滚动中 scrollTop 属性不会变化。

严格来说,上面的 scroll 事件不触发只是本坑的一个副作用,所以说不必考虑通过 touchmove 事件转发 scroll 事件等点子,scroll 事件触发了一样检测不到 scrollTop 属性的变化(当然检测手指的移动距离另说)。同样,检测滚动区域内部元素的 getBoundingClientRect 同样无效。

因此,在使用了这个属性之后不能检测到scrollTop属性的变化。

运行时通过 JS 动态添加元素溢出高度导致滚动失效

产生滚动要求设置滚动的元素(子元素)的高度大于其父元素的高度,这样才能触发滚动。如果不设置的话,iOS设备上底部会出现大片空白,如前文所述。

具体的设置方案

.outer { 

  overflow:scroll;

 -webkit-overflow-scrolling 

 }

.inner {

 height: calc(100% + 1px);

}

但是这样设置之后,滚动下拉加载不能实现。分析原因发现,需要给父元素动态绑定height,在vue的生命周期钩子的mounted阶段给父元素设置属性

 父元素

<div ref="wrapper" class='outer' :style="{ height: wrapperHeight + 'px' }">
添加height为wrapperHeight

mounted: function () {

  this.wrapperHeight = document.documentElement.clientHeight - this.$refs.wrapper.getBoundingClientRect().top

},
其中,document.documentElement.clientHeight为视口的高度(定值,例如667),设置之后,在chrome浏览器和安卓设备上均可以实现下拉加载,没有问题,但是在iOS设备上,却依然无效。

排查原因,发现是getBoundingClientRect()不兼容所致

getBoundingClientRect()方法的作用及兼容方案

getBoundingClientRect() 

这个方法返回一个矩形对象,包含四个属性:left、top、right和bottom。分别表示元素各边与页面上边和左边的距离。

例如,

var box=document.getElementById('box');         // 获取元素

alert(box.getBoundingClientRect().top);         // 元素上边距离页面上边的距离

alert(box.getBoundingClientRect().right);       // 元素右边距离页面左边的距离

alert(box.getBoundingClientRect().bottom);      // 元素下边距离页面上边的距离

alert(box.getBoundingClientRect().left);        // 元素左边距离页面左边的距离
注意:IE、Firefox3+、Opera9.5、Chrome、Safari支持,在IE中,默认坐标从(2,2)开始计算,导致最终距离比其他浏览器多出两个像素,我们需要做个兼容。

document.documentElement.clientTop;  // 非IE为0,IE为2

document.documentElement.clientLeft; // 非IE为0,IE为2

functiongGetRect (element) {

    var rect = element.getBoundingClientRect();

    var top = document.documentElement.clientTop;

    var left= document.documentElement.clientLeft;

    return{

        top    :   rect.top - top,

        bottom :   rect.bottom - top,

        left   :   rect.left - left,

        right  :   rect.right - left

    }

}

参照兼容方案,可以将绑定的父元素的高度进行兼容性设置。

this.wrapperHeight = this.$refs.wrapper.getBoundingClientRect().bottom - this.$refs.wrapper.getBoundingClientRect().top

这样设置之后,完成这个问题的修改。

其他可能的坑,笔者暂未遇到。。。

------------转载开始----------------

手势可穿过其他元素触发元素滚动(此坑转自文章

这个更奇葩。例中用一个半透明的 div 盖在了滚动区域 ul 上面(实践中可能是一个弹框的背部蒙版),甚至给 ul 自己加上了 pointer-events: none,手指在 div 上滑动仍然会触发 ul 的滚动。你可以在显示半透明蒙版时将 ul 的 -webkit-overflow-scrolling: touch 或 overflow: scroll 去掉,但是会造成屏幕明显的闪烁。如果给 body 的 touchmove事件 preventDefault() 可以防止触发滚动,但是是所有滚动区域都会失效。


有没有什么好的解决方案


使用 WKWebView 替换 UIWebView 内核

可能有些读者已经发现,scroll 事件不能触发的坑在 iOS Safari 和 iOS Chrome 浏览器中不存在,为什么呢?这里要从 iOS 上浏览器的发展史说起。

由于苹果公司对安全性等原因的考虑,苹果公司静止第三方浏览器在 iOS 设备上使用自己的浏览器的内核,换句话说,使用自己内核的浏览器都被禁止上架 AppStore。各大厂商无奈,于是长久以来,包括 Chrome 在内的所有第三方浏览器,都只是使用 iOS 系统内置的浏览器控件包一层外壳,这个控件就是 UIWebView。这个 UIWebView 不仅速度差,HTML5 支持率低,占用内存高,还有各种各样奇怪的问题。然而苹果公司却给自己的 Safari 浏览器开了后门。首先 Safari 使用的支持 JIT 编译的
JS 引擎内核 Nitro 比 UIWebView 里老旧的解释性 JavaScriptCore 内核速度搞数倍,然后 HTML5 支持度也比 UIWebView 高,还少了某些奇葩bug。久而久之就形成了 iOS 设备上 Safari 浏览器全面碾压其他第三方浏览器的现象。

在乔帮主撒手人寰不久之后,苹果公司口气终于松动,虽然没有放开第三方浏览器内核的限制,但把 Safari 的浏览器内核提取了出来开放第三方浏览器使用,那就是如今的 WKWebView(WK 即 Webkit 的缩写)。但由于 WKWebView 只支持 iOS8 以上系统,各大浏览器厂商并未立刻跟进。直到最近的 iOS9 时代,Chrome 成为第一个吃螃蟹的 APP,使用了 WKWebView 内核。测试数据表明,使用 WKWebView 内核的 Chrome 浏览器在速度和 HTML5 支持率上已经与 Safari
浏览器不相上下。紧接着 Mozilla 公司宣布 Firefox 登录 iOS 平台,使用的也是 WKWebView 内核(于是有了第一款基于 Webkit 内核的火狐浏览器 :)

不知苹果做了什么手脚,也许苹果的开发人员认为 WKWebView 的效能已经足以支撑在 scroll 事件中执行额外代码而不造成 UI 卡顿,总之在 WKWebView 内核中滚动可以正常触发 scroll 事件,当然也能正常获得 scrollTop 的值。然而经过测试第二个问题仍然存在。

在这里笔者强烈建议各个 APP 迁移内嵌浏览器至新的 WKWebView 内核。但是就我看到的,包括微信和饿了么在内,几乎所有的国产 APP 都还在使用 UIWebView 内核,这不得不说是一大前端开发之殇。

------------转载结束----------------------

参考文献

[1] htt
be6c
p://www.cnblogs.com/chris-oil/p/6164966.html

[2] https://segmentfault.com/a/1190000002783265
[3] http://www.cnblogs.com/leejersey/p/4127714.html
[4] http://patrickmuff.ch/blog/2014/10/01/how-we-fixed-the-webkit-overflow-scrolling-touch-bug-on-ios/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: