《五》移动端开发常见问题

1px 边框问题:

问题:在高清屏下,1px 边框会变粗。

产生原因:UI 设计师想要的 1px 的线,是在设备上能够显示的最小单位,即 1 物理像素;而开发工程师代码中的 1px,是 1 css 像素。在 dpr = 1 的标清屏下,一个方向上,1 css 像素 = 1 物理像素,此时没有问题;在 dpr > 1 的高清屏下,比如 dpr = 2 时,一个方向上,1 css 像素 = 2 物理像素,此时,如果开发工程师把边框设置为 1px,其实在设备上就是 2 物理像素,并不是最细的线了。

解决方法:

  1. 针对不同设备像素比直接设置对应的边框。
    // 不推荐。因为有些系统(例如:IOS8 之前)的浏览器不支持小数的像素
    @media screen and (-webkit-min-device-pixel-ratio: 2) {
         .border-1px {
         	border: 0.5px solid #ccc;
         }
    }
    @media screen and (-webkit-min-device-pixel-ratio: 3) {
         .border-1px {
         	border: 0.333333px solid #ccc;
         }
    }
    
  2. 伪类 + transform。
    // 推荐
    .border-1px {
    	position: relative;
    }
    .border-1px::after {
    	content: '',
    	position: absolute;
    	top: 0;
    	left: 0;
    	width: 100px;
    	height: 1px;
    }
    @ media (-webkit-min-device-pixel-ratio: 2) {
    	.border-1px::after {
    		transform:scaleY(0.5);
    	}
    }
    @ media (-webkit-min-device-pixel-ratio: 3) {
    	.border-1px::after {
    		transform:scaleY(0.333333);
    	}
    }
    

click 事件 300ms 延迟问题:

问题:手指触摸到屏幕的那一刻开始,到 click 事件被触发,可能会有 300ms 的延迟。

产生原因:双击缩放。移动端浏览器在点击屏幕后浏览器并不会马上触发 click 事件,而是会等待大概 300ms,来检测用户是否是双击。

解决方法:

  1. Touch 触摸事件不会有延迟,可以使用 touchstart 或者 touchend 代替 click 事件。
  2. 禁止双击缩放。浏览器就会认为不需要双击检测,点击屏幕后也就不会再延迟 300ms 了。可以使用以下方式中的任意一种:
    • 设置 touch-action: manipulation;,只允许滚动和持续缩放操作。
    • viewport 中设置禁止缩放(推荐):<meta name='viewport' content='width=device-wdith, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalabe=no' />

Touch 事件点击穿透问题:

* {
	margin: 0;
	padding: 0;
}
.mask {
	width: 100%;
	height: 100px;
	background-color: rgba(0, 0, 0, .2);
	position: absolute;
	top: 0;
	left: 0;
}
.btn {
	width: 100%;
	height: 100px;
}

<div id="mask" class="mask"></div>
<button id="btn" class="btn">提交</button>

// 点击遮罩层,但是也触发了按钮的 click 事件
const mask = document.getElementById('mask')
const btn = document.getElementById('btn')
mask.addEventListener('touchstart', () => {
	mask.style.display = 'none'
	console.log('touchstart 到了遮罩层')
})
btn.addEventListener('click', () => {
	console.log('clickm到了按钮')
})

请添加图片描述
点击遮罩层,首先触发 touchstart 事件,遮罩层隐藏;然后触发 click 事件,由于这时遮罩层已经消失,所以触发 click 事件的元素就变为了下一层的同样位置的按钮。

事件触发与否取决于用户是否有触发操作,和有没有绑定事件处理函数无关。所以即使遮罩层没有绑定 click 事件,但事实上也触发了的。

问题:某些时候,用手指进行点击触摸时,如果触摸的是层级比较高的上层的元素(例如:遮罩层),有可能导致下层的元素被点击中。也就是穿透了上面一层的元素,点到了下层的元素。

产生原因:移动端 Touch 事件会立即触发,而 click 事件会延迟一段时间再触发。

解决方法:

  1. 使用定时器延时消失上层元素。
    // 不推荐。比较生硬,感觉像卡顿了一下
    mask.addEventListener('touchstart', () => {
    	setTimeout(() => {
    		mask.style.display = 'none'
    	}, 200)
    	console.log('touchstart 到了遮罩层')
    })
    
  2. 上层元素消失过程中添加动画效果。
    // 推荐
    .mask {
    	opacity: 1;
    	transition: opacity .5s;
    }
    
    mask.addEventListener('touchstart', () => {
    	mask.style.opacity = 0
    	console.log('touchstart 到了遮罩层')
    })
    
    // opacity 为 0 只是将元素变成了透明,并没有真正消失,会导致再次想要点击下层元素点击不到,因此还需要监听到动画效果完成后,设置元素真正消失
    mask.addEventListener('transitionend',  () => {
    	mask.style.display = 'none'
    })
    

图片显示问题:

前端引入图片显示有两种方式:通过 img 标签引入和通过背景图片引入。

通过 img 标签引入:

问题:在 PC 端的时候,直接给通过 img 标签引入的图片设置固定宽高显示即可。但是在移动端,由于屏幕大小多变,直接给图片设置固定宽高就不可取了。那么,如何让图片在移动端更好地显示呢?

解决方法:

  1. 宽高使用百分比,并且不同时设置,只设置其中的一个,让图片能够等比例缩放。

    缺点:当图片实际的宽度小于父容器的宽度时,图片会被强行拉伸到与父容器同宽,导致图片失真。

    img {
    	width: 100%;
    }
    
  2. 第一种解决方法中,使用 max-width 代替 width。

    缺点:当图片实际的宽度小于父容器的宽度时,图片不会随着父容器宽度的变大而进一步拉伸,导致父容器中会出现一片空白区域。

    img {
    	max-width: 100%;
    }
    

通过背景图片显示引入:

.bg-container {
	width: 100%;
	height: 200px;
	background: url(./bg.png) no-repeat;
}

<div class="bg-container"></div>

问题:背景图片的大小不会变化,但是随着屏幕宽度的变化,越小的屏幕图片显示越不完整。

解决方法:

  1. 如果背景区域的高度是固定的,可以使用 background-size: cover; 等比例缩放背景图片以完全覆盖背景区域,但是可能会导致背景图片部分看不见。
    .bg-container {
    	width: 100%;
    	height: 200px;
    	background: url(./bg.png) no-repeat;
    	background-size: cover;
    }
    
  2. 如果背景区域的高度是不固定的,可以让背景区域的宽高比等于背景图片的宽高比,然后让背景图片覆盖整个背景区域。
    .bg-container {
    	width: 100%;
    	background: url(./bg.png) no-repeat;
    	// 宽度的百分比是相对于父容器的宽度,高度的百分比是相对于父容器的高度。因此不能直接使用 height 设置百分比。
    	// padding 的百分比是相对于父容器的宽度。因此可以使用 padding-top 设置百分比撑起父元素的高度。
    	padding-top: 50%; // 假设背景图片的宽度为 100px,高度为 50px,那么宽高比就为 100:50
    	background-size: cover;
    }
    

IOS 系统和安卓系统的兼容性问题:

  1. PC考虑的是浏览器的兼容性,而移动端开发考虑的更多的是手机兼容性。(因为目前不管是 android 手机还是 ios 手机,一般浏览器使用的都是 webkit 内核)
  2. 在部分事件的处理上,移动端多出来的事件是触屏事件,而缺少的是 hover 事件。 另外包括移动端弹出的手机键盘的处理等。
文字和图片在一行显示,当使用 flex 布局之后,图片被压扁变形的问题:

解决方法:可以对图片设置 flex-shrink: 0;,即使空间不足,图片也不缩小,否则默认 flex-shrink: 1; ,图片将自动缩小。

IOS 系统:

IOS8 之前的浏览器,不支持小数像素。部分安卓系统的浏览器,也不支持小数像素。

z-index 无效问题:

Safari 浏览器直接忽略 z-index,可以使用 translateZ 来替代,translateZ 值越大,越在上层。

点击 input 输入框,页面会自动放大:

产生原因:IOS 有点击输入框自动放大的功能,认为这样用户体验好。

解决方法:使用禁止缩放页面来解决。

<meta name="viewport" content="width=device-width, initial-scale=1.0,minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">  
有时莫名出现没内容的地方一片白(在设置了背景色之后即可看到这个问题的存在):

解决方法:在底部加个透明度为 0 的标签。

<div class="footer">iOS有时莫名出现没内容的地方一片白</div>

.footer{
	position: fixed;
    bottom: 0;
    right: 0;
    color: transparent;
}

安卓系统:

键盘弹起时页面布局压缩变形的问题:

产生原因:安卓手机出现软键盘导致页面压缩变形,苹果手机不会。原因是安卓手机计算的是页面可显示的区域,软键盘那块区域不算,所以在 body 没有固定的情况下就会被压缩、顶起。

解决方案:在页面加载完后,获取当前屏幕的高度对 body 进行固定赋值。

mounted(){
	document.getElementsByTagName('body')[0].style.height=`${document.documentElement.clientHeight}px`
}
absolute 或 fixed 定位在底部的元素被键盘顶起的问题:

解决方法:

  1. 初始设置默认屏幕高度和实时屏幕高度。
  2. 通过 window.onresize 监听屏幕的高度变化,获取实时屏幕高度。
  3. 当默认屏幕高度小于实时屏幕高度时,隐藏底部定位的元素。
<div class="footer" v-if="isShowFooter">
      <img src="../../assets/login/ic_agree.png" class="agree-img"/>
</div>

data(){
	return {
		isShowFooter:true,
        docmHeight: document.documentElement.clientHeight,  //默认屏幕高度
        showHeight: document.documentElement.clientHeight,   //实时屏幕高度
	}
}
watch:{
        showHeight() {
            if(this.docmHeight > this.showHeight){
                this.isShowFooter = false
            }else{
                this.isShowFooter = true
            }
        }
},
 mounted() {    
        // window.onresize监听页面高度的变化
        window.onresize = ()=>{
            return(()=>{
                this.showHeight = document.body.clientHeight;
            })()
        }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值