移动端开发的几个常见问题

移动端适配

原理: 动态 rem,淘宝 flexilble
设备像素比(dpr) = 物理像素 / 设备独立像素
window.devicePixelRatio 获取到当前设备的 dpr
在 html 上加上 data-dpr 值,通过 css 媒体查询
flexible 实际上就是能过 JS 来动态改写 meta 标签,动态改变 html data-dpr 属性,动态改变 rem
使用 px2rem 把设计搞的 px 改成 rem
可查看官方文档
解决方案:

<meta name="flexible" content="initial-dpr=2" />
<script src="http://g.tbcdn.cn/mtb/lib-flexible/0.3.4/??flexible_css.js,flexible.js"></script>

在 vue 使用 vw 实现适配

0.5px 的 border

原因: 部分浏览器不支持低于 1px 的 border

解决方案 1 : 使用 css3 box-shadow

.box-shadow-1px {
box-shadow: inset 0px -1px 1px -1px #c8c7cc;
}

解决方案 2: 利用 css3 transform scale(0.5)

创建伪元素,然后相对定位,transform scale(0.5)

.div{
    position:relative;
}

&::before{
    content: ' ';
    display:blocl;
    transform:scale(0.5);
    position:absolute;
    border:1px solid #333;
    top:-50%;
    right:-50%;
    bottom:-50%;
    left:-50%;
}

300ms 延迟

原因:300ms 延迟主要是因为双击缩放/双击滚动,浏览器双击会缩放到原始比例,当进行正常点击的时候,浏览器会延迟 300ms,判断用户是否再次点击屏幕.

解决方案 1: 通过 meta vp,设置用户不可缩放
缺点:禁用缩放会损害移动端网页的可用性和可访问性,safari 也不支持.例如:可能无法放大网页中的一张图片或一段字体较小的文字.


<meta name="viewport" content="initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />

解决方案 2:视窗设置为设备宽度
原理:原始尺寸时禁用双击缩放,但是用户可自行放大.


<meta name="viewport" content="width=device-width">

解决方案 3 :FastClick
移动端事件触发顺序,当用户点击一个元素,会经过 touch start,touch move,touch end,click.
原理:fastclick 当检测到 touch end 时,通过 dom 自定义事件模拟一个 click 事件,并把浏览器自身的 300ms 之后的 click 事件屏蔽.

window.addEventListener( "load", function() {
    FastClick.attach( document.body ); // 直接绑定到 <body> 上可以确保整个应用都能受益
}, false );

解决方案 4 :touch-action 对 mouse,touch,stylus 进行统一处理.但是现阶段兼容性不好.
原理:CCS3 属性,默认是 auto,当设置成 none 时,关闭用户代理的行为(包括但不限于双击缩放)

.div{
    touch-action :none
}

点透现象

当 A 的 z-index 大于 B,A 在 B 之上,A 触发 touch,后立即消失,B 绑定 click 事件.

原因:当用户触碰屏幕时,生成两个事件,touch 与 click,A 在 touch 后消失,但有 300ms 的延迟,所以在 B 上会触发 clck 事件.

解决方案 1: 隐藏蒙层的执行 300ms 延迟的方法

$("#id").on('tap',function(ev){
    setTimeout(function(){
        $("#id").hide();
    },320)
})

解决方案 2: FastClick

解决方案 3: 使用 touchend 并阻止默认行为

 $("#id").on("touchend", function (event) {
     //很多处理比如隐藏什么的
     event.preventDefault();
 });

移动端 meta 标签

<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" >

<!--2:忽略将数字变为电话号码-->
<meta  name="format-detection" content="telephone=no">

<!--3:忽略识别邮箱-->
<meta name="format-detection" content="email=no" />

<!--4:IOS中Safari允许全屏浏览-->
<meta name="apple-mobile-web-app-capable" content="yes" >

固定定位布局 键盘挡住输入框内容

  1. 通过绑定窗口改变事件,监听键盘的弹出。然后去改变固定定位元素的位置。默认键盘的宽度应该是页面的 2 分之一,所以我们位移的距离改成键盘的二分之一就可以
window.onresize = function(){
    //$(".mian")就是固定定位的元素
    if($(".mian").css('top').replace('px','') != 0){
        $(".mian").css('top',0);
    }else{
        var winHeight = $(window).height();
        $(".mian").css('top',-(winHeight/4));
    }
}

  1. 通过定时器实时监听是否触发 input。如果触发 input 框 就把固定定位,改变成静态定位。这样就会浏览器会总动把内容顶上去。
function fixedWatch(el) {
    //activeElement 获取焦点元素
    if(document.activeElement.nodeName == 'INPUT') {
        el.css('position', 'static');
    } else {
        el.css('position', 'fixed');
    }
}

setInterval(function() {
    fixedWatch($('.mian'));
}, 500);

移动端兼容问题

  1. 移动端 button/input 不一样,需要去除默认样式
//去掉webkit的滚动条——display: none;
//其他参数
::-webkit-scrollba //滚动条整体部分
::-webkit-scrollbar-thumb   //滚动条内的小方块
::-webkit-scrollbar-track   //滚动条轨道
::-webkit-scrollbar-button  //滚动条轨道两端按钮
::-webkit-scrollbar-track-piece  //滚动条中间部分,内置轨道
::-webkit-scrollbar-corner       //边角,两个滚动条交汇处
::-webkit-resizer            //两个滚动条的交汇处上用于通过拖动调整元素大小的小控件

// 禁止长按链接与图片弹出菜单
a,img { -webkit-touch-callout: none }

// 禁止ios和android用户选中文字
html,body {-webkit-user-select:none; user-select: none; }

// 改变输入框placeholder的颜色值
::-webkit-input-placeholder { /* WebKit browsers */
color: #999; }
:-moz-placeholder { /* Mozilla Firefox 4 to 18 */
color: #999; }
::-moz-placeholder { /* Mozilla Firefox 19+ */
color: #999; }
:-ms-input-placeholder { /* Internet Explorer 10+ */
color: #999; }
input:focus::-webkit-input-placeholder{ color:#999; }

// android上去掉语音输入按钮
input::-webkit-input-speech-button {display: none}

// 阻止windows Phone的默认触摸事件
/*说明:winphone下默认触摸事件事件使用e.preventDefault是无效的,可通过样式来禁用,如:*/
html { -ms-touch-action:none; } //禁止winphone默认触摸事件




//ios用户点击一个链接,会出现一个半透明灰色遮罩, 如果想要禁用,可设置-webkit-tap-highlight-color的alpha值为0去除灰色半透明遮罩;
//android用户点击一个链接,会出现一个边框或者半透明灰色遮罩, 不同生产商定义出来额效果不一样,可设置-webkit-tap-highlight-color的alpha值为0去除部分机器自带的效果;
//winphone系统,点击标签产生的灰色半透明背景,能通过设置<meta name="msapplication-tap-highlight" content="no">去掉;
//特殊说明:有些机型去除不了,如小米2。对于按钮类还有个办法,不使用a或者input标签,直接用div标签
a,button,input,textarea {
    -webkit-tap-highlight-color: rgba(0,0,0,0);
    -webkit-user-modify:read-write-plaintext-only; //-webkit-user-modify有个副作用,就是输入法不再能够输入多个字符
}
// 也可以
* { -webkit-tap-highlight-color: rgba(0,0,0,0); }
//winphone下
<meta name="msapplication-tap-highlight" content="no">
  1. 手机拍照上传图片

IOS 有拍照,录像,选区本地图片功能,安卓只有选择本地图片功能