一 前言
笔者最近一直在开发京东app嵌入的h5项目和微信小程序商城项目,在此期间遇到很多坑。这篇文章主要是针对 h5| Hybrid | 微信小程序 三个方向来讲述我遇到的坑,以及详细讲解我是如何解决问题的。
一直以来,移动端适配就是一个令人头疼的问题。如果想要吃透移动端,还需要不少的实践经验,有的时候在pc
端调试没有问题,但是在m端就会出现问题。以下这16个问题是我在实际工作中遇到的,亲自奉上给大家。希望大家收藏一波,以备不时之需。
喜欢笔者的可以「点赞 + 收藏 」 一波,持续更新前端硬核文章。
M端h5踩坑总结
以下是京东嵌入h5,h5落地页,遇到的问题。我用一个思维导图表示出来。
1 ios::postion:fixed 定位抖动跳屏问题
背景
在开发京东app,Hybrid h5
业务页面的时候,遇到一个非常棘手的问题,因为这个页面类似京东app商品详情页面的动画效果。 动画效果如下所示。安卓手机正常,但是ios手机出现,滑块抖动问题,图片会出现闪动的效果。这个问题困扰了很久,网上搜索了大量的解决方案,都没有实际解决问题,自己也尝试了几种方法,也没有成功,当时很奔溃😭😭😭,最后还是灵光一现,想到了一个巧妙的解决方案😂。
整个流程就是,当视图容器向上滑动的时候,商品卡片容器需要缓慢移动,首先需要将商品卡片需要脱离标准流,设置定位position:fixed
固定定位。然后控制top
值来控制滑块的缓慢移动。但是在容器向上滑动的过程中,滑块会出现抖动
,闪动
的效果。
🤔分析这个原因,应该是ios
对position
表现不友好的原因,这种类似的原因在小程序里也很常见。
解决方案
网上搜索和自己探索的失败解决方案
① 给顶级元素设置height:100%
( 并没有奏效 ) 。
② 增加 transform: translate(0)
属性 ( 并没有奏效 )
③ 改变布局由fixed
定位,改成absolute
定位,滚动条基于自身。( 能够从根本上解决偶尔跳屏的问题,但是随之而来的就是ios
滚动条问题,基于document
才能有效触发,遂放弃此方案)
④ 不改变布局的情况下,由fixed
定位,改成absolute
定位,滚动条基于document
,定位值完全取决于数据驱动。(能够从根本上解决偶尔跳屏的问题,但是随之而来的就是要不断改变自身的top值 ,导致更新会慢的情况 ,用户体验不好,流畅度欠佳,遂放弃此方案 )
⑤ -webkit-overflow-scroll:touch
解决滑动无惯性( 并没有奏效 )
⑥ background-attachment:fixed
( 并没有奏效 )
解决方案
试了好久,终于想到了一个解决方法。继续使用 fixed
定位,因为我们这里需要通过定位,抖动不是单纯fixed
定位的原因。和频繁改变top
值也有很大关系。放弃改变top
值 ,运用transform: translateY
来使视图上下移动。
<view class="scroll_box" style={
{
transform:`translateY(${
top }px)` }} >
<!-- 很多东西 -->
</view>
.scroll_box{
position:fixed;
}
2 android问题:border-radius:50% 圆角被拉伸问题
背景
当我们期望用 border-radius:50%;
来绘制圆点的时候。如果圆比较大可能不是很明显,但是如果圆比较小的时候,会出现明显的不圆,圆被拉伸的情况。
大致效果如下所示。
🤔分析原因, 在移动端通常会适配不同的手机,所以使用rem
布局,,rem
在换算为px
时,会是一个带小数点的值,安卓对小于1px
的做了处理(不同浏览器对小于1px
的处理方式不同,有的采用四舍五入,有的大于某个值展示1px
否则就舍去),从而导致圆角不圆;在ios
下就没有这个问题。
解决方案
我们先把已知视图宽高变成2倍 ,然后用 transform: scale(.5)
让视图缩小50% ,就可以在 android
得到很圆的效果。亲测这个方法非常奏效,形成的圆非常的圆。
我们举个例子🌰:
<div class="round" ></div>
没有做兼容之前的样式,
.round{
border-radius:50%;
width:10px;
heigth:10px;
}
改成
.round{
border-radius:50%;
width:20px;
heigth:20px;
transform: scale(.5);
}
这里用的taro-h5
, px
会被自动转化成rem
。
问题演变
有的时候我们在给元素设置高度非常小的时候也会出现这个问题。
<view class='box' />
.box{
width:100px;
height:1px;
}
因为我们高度设置为height:1px
,当taro
给转换成rem
的时候,也会出现四舍五入的情况,结果将1px
弄没了,变成了0px
,于是乎就造成了1px
元素无法显示的bug
,解决方案和上述的原理一样。将高度变成原来的2倍,再通过transform: scaleY(.5);
y方向变为原来的二分之一。
.box{
width:100px;
height:2px;
transform: scaleY(.5);
}
3 iOS问题 :最后子元素ios底部设置margin-bottom无效
背景
这个问题在ios
环境下,还是很容易发生的。当视图容器的最后一个元素设置 margin-bottom
,期望距离整个容器视图有一个距离的时候,发现在安卓手机正常,但是在ios
下,会出现margin-bottom
无效的情况。
解决方案
这个的解决方案也非常非常的简单,将margin-bottom
改成padding-bottom
就能根本的解决问题。
例子🌰:
<div class="box" ></div>
.box{
margin-bottom: 148px;
}
改成
.box{
padding-bottom: 148px;
}
4 ios 屏幕上拉下滑出现空白
背景
手指按住屏幕下拉,屏幕顶部会多出一块空白区域。手指按住屏幕上拉,底部多出一块空白区域。空白区域的颜色,在不同app
平台打开,颜色会有差别,嵌入京东app h5中的空白背景色为白色,但是在微信中为灰色。
🤔分析原因:
在 iOS
中,手指按住屏幕上下拖动,会触发 touchmove
事件。这个事件触发的对象是整个 webview
容器,容器自然会被拖动,剩下的部分会成空白。
效果如下:
解决方案
1 障眼法,很管用
比如对于京东app这种白色背景,如果我们background
也是白色的,完全可以用整个顶端容器,定位填充整个容器来解决这个问题。这样视图不会跟随上拉下滑而移动。如果空白颜色和背景颜色一致,视觉上就会抵消滑动效果。根本上解决出现空白的问题。
一言不合上代码😜。
<div id="root" >
<!-- 此处省略很多内容 -->
</div>
#root{
position: fixed;
left:0;
top:0;
bottom: 0;
right: 0;
}
2 监听事件,禁止上滑下滑
这种方法比较靠谱,俗话说解铃还须系铃人
,这个问题根本原因是 touchmove
引起的,那么从根本上解决问题,还是要从touchmove
这个事件入手。我们需要监听移动端document
的 touchmove
然后通过 preventDefault
方法,阻止同一触点上所有默认行为,比如滚动事件。这里要注意的是什么时候,不让滑动,什么时候让滑动。
<div ref="root" ></div>
const box = this.$refs.root
box.addEventListener('touchmove',function(e){
/* 让视图容器正常滚动 */
e._isScroller = true
})
/* 禁止上滑,下滑 */
document.body.addEventListener('touchmove', function (e) {
if (e._isScroller) return
/* 阻止默认事件 */
e.preventDefault()
}, {
passive: false
})
5 移动端问题: input 的 placeholder 垂直方向不居中问题
背景
在开发移动端的时候,会遇到 input
的 placeholder
垂直方向不居中的情况。
解决方案
input
的placeholder
会出现文本位置偏上的情况:PC端设置line-height
等于height
能够对齐,而移动端仍然是偏上,解决方案时是设置css line-height:normal
;
html:
<input class="input" />
样式:
.input{
line-height:normal;
}
6 IOS 滑动问题 -webkit-overflow-scrolling : touch 卡住不动问题
背景
在ios
页面向上向下滑动的过程中,会出现卡顿,不流畅的现象,具体问题如下:
1 在safari
上,使用了-webkit-overflow-scrolling:touch
之后,页面偶尔会卡住不动。(中招)
2 在safari
上,点击其他区域,再在滚动区域滑动,滚动条无法滚动的(中招)。
在解决这个问题之前,我们先理解-webkit-overflow-scrolling
的两个属性
1 auto
: 使用普通滚动, 当手指从触摸屏上移开,滚动会立即停止。
2 touch
: 使用具有回弹效果的滚动,当手指从触摸屏上移开,内容会继续保持一段时间的滚动效果。继续滚动的速度和持续的时间和滚动手势的强烈程度成正比。同时也会创建一个新的堆栈上下文。
解决方案
<div id="app" style="-webkit-overflow-scrolling: touch; ">
<div style="min-height:101%"></div>
</div>
或
<div id="app" style="-webkit-overflow-scrolling: touch; ">
<div style="height:calc(100%+1px)"></div>
</div>
方法就是在webkit-overflow-scrolling:touch
属性的下一层子元素上,
将height
加1%或1px。从而主动触发scrollbar
。
7 移动端适配:页面放大缩小
背景
如果没有使用taro
等跨平台框架构建的h5,当在M端展示h5的时候,双击或者双指张开手指页面元素,页面会放大或缩小。
针对这个情况,实际不算一个bug
,因为html
本身就支持缩放。在pc
端的时候,我们可以控制鼠标滚轮控制页面缩放,但是在移动端这个行为也存在。但是对于嵌入的 M端 h5页面,我们不需要这个功能。
解决方案
我们可以通过 meta
元标签标准中有个 中 viewport
属性,用来控制页面的缩放,一般用于移动端。
我们先看看taro-h5
是怎么适配的.
<meta content="width=device-width,initial-scale=1,user-scalable=no" name="viewport">
核心user-scalable=no
,没错,就是通过这个属性来阻止缩放行为的。
总结
下一篇中,我们将继续介绍踩坑记录。