导语
这期讲一下移动端开发时常见到的一些问题,内容包括1像素边框、300ms延迟以及zepto的tap的bug,下面的所有代码均在chrome的iPhone6Plus的设备模拟器环境下测试;
1像素边框的问题
出现1px边框的问题由来
iPhone的dpr>=2,1px由4dp构成,相当于宽高都放大1倍,它们显示出2dp的效果,PC端由于尺寸较大,所以差距不明显,但是在移动端的小屏幕上,差距就非常突出;
所以这就是为什么在PC端设置1px,在dpr>=2的移动端会显示出"2px"的效果;
解决问题的思路是:进行设备检测,当dpr>=2并且为移动设备时,去除PC端设置的border,添加适配移动端元素的border的类,具体就是将border缩放为原来的0.5
如果只是给元素添加下边框,可以采用以下hack方案:
<div class="foo">
1px border question
</div>
.foo{
position: relative;
}
.foo::after{
content:'';
width: 100%;
display: block;
postion: absolute;
bottom: 0;
border: 1px solid;
transform: scaleY(0.5)
}
如果给元素添加全边框,可以采用一下方案:
<div class="foo">
1px border question
</div>
.onePixel{
position: relative
border: none;
&::after{
content:'';
display: block;
border: 1px solid;
box-sizing: border-box;
width: 200%;
height: 200%;//缩放0.5后,变为100%;
transform: scale(0.5);
position: absolute;
top: 0;
left: 0;
}
}
if(window.devicePixelRatio && window.devicePixelRation>=2 && /iPhone/i.test(navigator.userAgent)){
document.querySelector('.foo').className = 'foo onePixel'
}
完整代码见code,童鞋们可以打开设备模拟器放大到150%自行观察区别;
300ms延迟
移动端的click事件触发后慢上300ms
默认的viewport都是980px->许多页面将缩放显示-> 用户往往初次进入时需要双击页面 -> 为了判断是否双击,当点击之后给予300ms的反应时间
click 300ms
如何破解300ms问题?
- 为head添加viewport
<meta name="viewport" content="width=device-width,initial-scale=1,max-scale=1,no-scalable=no">
上述元信息表明默认不进行缩放,按照设备尺寸去设置viewport;
既然设备知道不用缩放,所以也就不用响应300ms;
但缺点是万一用户要缩放呢?
code
- 使用tap事件代替click事件,是自定义的click事件
zepto库提供了click事件的替代事件tap;
tap事件的原理
zepto的源码是点击后点击位置不超过30像素,则在250ms后出发tap事件;
tap的bug——点透
看了些资料,据闻zepto的tap事件在有两个元素层叠的时候,上层蒙层元素监听tap事件点击后消失,下层元素监听click事件,会发生点透的bug;
为什么?
tap事件的延迟是250ms,click是300ms,所以当上层元素在250ms触发后消失,下层元素再过50ms才接受到click事件,所以会发生类似的现象;
这个bug本质就是打个时间差,上层元素250ms反应,下层元素300ms才反应;
code
tap的解决方案
总结:
- 由于手机设备的dpr缘故导致1px的显示效果在PC端和手机端显示不一致,解决方案是通过在元素内部添加伪类的方式制造出经过缩放0.5倍的1px边框;
- 由于以前手机端往往在初次进入页面时需要双击缩放,所以iPhone设置了一个300ms毫秒的方法响应用户操作,由此也带来了不小的麻烦;
- 解决300ms方案包括设置viewport和或者是采用tap事件;
- tap事件又会带来点透的bug,解决方案可以是延迟tap触发或所有的元素都使用触发;