移动端H5页面开发坑点指南

前言

在平时的H5移动端开发时,咱们不免会遇到各类各样的坑点,这篇文章就带着你们来看看怎么解决,文章较长,建议收藏方便之后查阅!javascript

前方高能!

canvas在retina屏模糊

只须要将画笔根据像素比缩放便可css

run(canvasEl) {
    const canvas = canvasEl;
    const ctx = canvas.getContext('2d');
    const devicePixelRatio = window.devicePixelRatio || 1;
    const backingStorePixelRatio = ctx.webkitBackingStorePixelRatio ||
    ctx.mozBackingStorePixelRatio ||
    ctx.msBackingStorePixelRatio ||
    ctx.oBackingStorePixelRatio ||
    ctx.backingStorePixelRatio || 1;

    const ratio = devicePixelRatio / backingStorePixelRatio;
    if (devicePixelRatio !== backingStorePixelRatio) {
      const oldWidth = canvas.width;
      const oldHeight = canvas.height;

      canvas.width = oldWidth * ratio;
      canvas.height = oldHeight * ratio;

      canvas.style.width = `${oldWidth}px`;
      canvas.style.height = `${oldHeight}px`;
      ctx.scale(ratio, ratio);
    }
  },
复制代码

用同等比例的图片在PC机上很清楚,可是手机上很模糊,缘由是什么呢?

经研究发现是devicePixelRatio做怪,由于手机分辨率过小,若是按照分辨率来显示网页字会很是小,因此苹果就把iPhone 4的960640分辨率在网页里只显示了480320,这样devicePixelRatio=2;如今android比较乱,有1.5/2/3等,想让图片在手机里显示更为清晰必须使用2x的背景图来代替img标签(通常状况都是用2倍),例如一个div的宽高是100100,背景图必须得200200,而后background-size:contain;,这样显示出来的图片就比较清晰了;代码以下:html

background:url(../images/icon/all.png) no-repeat center center;
   -webkit-background-size:50px 50px;
   background-size: 50px 50px;
   display:inline-block; 
   width:100%; 
   height:50px;
复制代码

启动或禁用自动识别页面中的电话号码;

<meta name="format-detection" content="telephone=no"> 
复制代码

默认状况下设备会自动识别任何多是电话号码的字符串,设置telephone=no能够禁用这项功能,设置不识别邮箱和地址也同理vue

h5网站input设置为type=number的问题

h5网页input的type设置为number通常会产生三个问题:html5

问题1:maxlength属性很差用java

<input type="number" oninput="checkTextLength(this ,10)">
<script type="text/javascript"> function checkTextLength(obj, length) { if(obj.value.length > length) { obj.value = obj.value.substr(0, length); } } </script>
复制代码

问题2:form提交的时候默认取整android

<input type="number" step="0.01" /> //input中type=number通常会自动生成一个上下箭头,点击上箭头默认增长一个step,点击下箭头默认会减小一个step;number中默认step是1,也就是step=0.01能够容许输入2位小数,而且点击上下箭头分别增长0.01和减小0.01;step和min一块儿使用时数值必须在min和max之间
复制代码

问题3:部分安卓手机出现样式问题ios

去除input默认样式的方法:web

input,textarea {
    border: 0;
    -webkit-appearance: none; //可同时屏蔽输入框怪异的内阴影,解决iOS下没法修改按钮样式,测试还发现,加了此属性后,iOS下默认仍是有圆角的,不过能够用border-radius属性修改
}
复制代码

select下拉选择设置问题

问题1:右对齐实现canvas

设置以下属性

select option {
    direction: rtl;
}
复制代码

问题2:禁用select默认箭头

::-ms-expand修改表单控件下拉箭头,设置隐藏并使用背景图片来修饰

select::-ms-expand { display:none; }
复制代码

移动端HTML5 audio autoplay失效问题

因为自动播放网页中的音频或视频会给用户带来困扰或没必要要的流量消耗,因此苹果系统和安卓系统一般都会禁止自动播放和使用JS的触发播放,必须由用户来触发才播放;解决方法思路:先经过用户touchstart触碰触发播放并暂停(让音频开始加载),后面用JS再操做就没问题了;解决代码:

document.addEventListener('touchstart', function () {
    document.getElementsByTagName('audio')[0].play();
    document.getElementsByTagName('audio')[0].pause();
});
复制代码

CSS动画页面闪白,动画卡顿,图片错乱的问题

1.尽量地使用合成属性transform和opacity来设计CSS3动画,不使用position的left和top来定位

2.开启硬件加速

-webkit-transform: translate3d(0, 0, 0);
-moz-transform: translate3d(0, 0, 0);
-ms-transform: translate3d(0, 0, 0);
transform: translate3d(0, 0, 0);
复制代码

浮动子元素撑开父元素盒子高度(BFC)

解决方法以下:

1.父元素设置为 overflow: hidden;

2.父元素设置为 display: inline-block;等

这里两种方法都是经过设置css属性将浮动元素的父元素变成BFC(块级格式化上下文)元素,使子元素高度能够撑开父元素;不过最好使用方法1,由于inline-block元素自己会自带一些宽高度撑开其自己

往返缓存问题

点击浏览器的回退有时候不会自动执行js,特别是在mobilesafari中;这与往返缓存(bfcache)有关系,解决方法:

window.onunload = function(){};
复制代码

定位的坑

在IOS下fixed定位在软键盘顶起时会失效,因此咱们在开发时统一使用absolute代替

audio元素和video元素在ios和andriod中播放问题

<audio src="music/bg.mp3" autoplay loop controls>你的浏览器还不支持哦</audio> //音频,写法一
<audio controls="controls"> //音频,写法二   
    <source src="music/bg.ogg" type="audio/ogg"></source>
    <source src="music/bg.mp3" type="audio/mpeg"></source> //优先播放音乐bg.ogg,不支持在播放bg.mp3    
</audio>
复制代码

到这里通常均可以播放音乐了,若是还不行颇有多是微信的限制

问题3:微信的限制

若是是微信的限制,这时须要调用微信接口,页面先引入:

<script src="http://res.wx.qq.com/open/js/jweixin-1.0.0.js"></script>
复制代码

而后JS写入微信事件:

document.addEventListener("WeixinJSBridgeReady", function() {
    document.getElementById('music').play();
}, false);
复制代码

小结:

1.audio元素的autoplay属性在IOS及Android上没法使用,在PC端正常

2.audio元素没有设置controls时,在IOS及Android会占据空间大小,而在PC端Chrome是不会占据任何空间

问题4:Safari浏览器自动播放

document.addEventListener('touchstart', function(){   
    audio.play();
}, false);
复制代码

ios系统不支持动画暂停样式(animation-play-state)

H5页面通常都会有BGM,也会提供一个旋转的音乐图标供用户开启关闭音乐;咱们但愿当用户点击音乐按钮时图标中止旋转,再点图标顺着以前中止的位置继续跑动画;animation-play-state是最简便的方式,然而ios不支持

目前的解决方案是:音乐图标负责跑动画,图标父级元素负责记录中止时的转动值

ios防止长按页面元素被选中

解决:加入样式可禁止用户进行复制,ios和通常的安卓均可以解决

-webkit-touch-callout:none;  //系统默认菜单被禁用;能够实现页面由于长按弹出各类操做窗口
-webkit-user-select:none; //webkit浏览器  
-khtml-user-select:none; //早期浏览器 
-moz-user-select:none; //火狐 
-ms-user-select:none; //IE10 
user-select:none; 
复制代码

添加完这段代码后在IOS上会有问题,这时发现input框没法正在输入内容了;形成这个缘由是-webkit-user-select:none;这个属性,解决方法就是在css文件中同时设置一下input的属性,以下:

input {      
     -webkit-user-select:auto; //webkit浏览器    
}
复制代码

html5碰到上下拉动滚动条时卡顿/慢怎么解决

首先你可能会给页面的html和body增长了height: 100%, 而后就可能形成IOS上页面滑动的卡顿问题。

解决方案是: 1.让html和body固定100%(或者100vh), 2.而后再在内部放一个height:100%的div,设置overflow-y: auto;和-webkit-overflow-scrolling: touch;

overflow-x:auto在iOS有兼容问题,解决方法:

.scroll-box {
  /* 模态框之类的div不能放在这个容器中,不然关闭模态框有时候关闭不了 */
  height: 100%;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  overflow-scrolling: touch;
}
复制代码

点击元素产生背景或边框怎么去掉

a,button,input,textarea{ -webkit-tap-highlight-color: rgba(0,0,0,0); -webkit-user-modify:read-write-plaintext-only; //-webkit-user-modify有个反作用,就是输入法再也不可以输入多个字符 } 或 a,button,input,textarea{ -webkit-tap-highlight-color: rgba(0,0,0,0); }

浏览器后退不刷新

这种状况是之前遇到的,这里也说下;主要会发生在webview里多一点,当点击后退时页面以缓存形式出现,而不是刷新后的,不少状况下这不是你预期的效果,解决方法是用js:

方法1window.addEventListener('pageshow', () => {
  if (e.persisted || (window.performance && 
    window.performance.navigation.type == 2)) {
    location.reload()
  }
}, false);

方法2:
window.history.replaceState(null, '', window.location.href + '?timestamp=' + new Date().getTime());

复制代码

onpageshow每次页面加载都会触发,不管是从缓存中加载仍是正常加载,这是他和onload的区别;persisted判断页面是否从缓存中读出

页面经过历史记录和前进后退访问时。type值为2

transition清除闪屏

-webkit-transform-style: preserve-3d; //设置内嵌的元素在 3D 空间如何呈现:保留3D
-webkit-backface-visibility:hidden; //设置进行转换的元素的背面在面对用户时是否可见:隐藏
-webkit-perspective: 1000;
复制代码

解决active伪类失效

<body ontouchstart></body>
复制代码

顶部状态栏背景色

apple-mobile-web-app-capable是设置Web应用是否以全屏模式运行;语法:
<meta name="apple-mobile-web-app-capable" content="yes"> //content设置为yesWeb应用会以全屏模式
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
复制代码

说明:除非你先使用apple-mobile-web-app-capable指定全屏模式,不然这个meta标签不会起任何做用;若是content设置为default,则状态栏正常显示;若是设置为blank,则状态栏会有一个黑色的背景;若是设置为blank-translucent,则状态栏显示为黑色半透明;若是设置为default或blank,则页面显示在状态栏的下方,即状态栏占据上方部分;页面占据下方部分,两者没有遮挡对方或被遮挡;若是设置为blank-translucent,则页面会充满屏幕,其中页面顶部会被状态栏遮盖住(会覆盖页面20px高度,而iphone4和itouch4的Retina屏幕为40px);默认值是default。

ios专区

IOS中对input键盘事件keyup/keydown/keypress等支持很差的问题

经查发现,IOS的输入法(不论是第三方仍是自带)能检测到英文或数字的keyup,但检测不到中文的keyup,在输入中文后须要点回退键才开始搜索;解决办法是用html5的oninput事件去代替keyup,经过以下代码达到相似keyup的效果;

1.修改了input:checkbox或input:radio元素的选择中状态,checked属性发生变化

2.修改了input:text或textarea元素的值,value属性发生变化

3.修改了select元素的选中项,selectedIndex属性发生变化 统一使用input监听

<input type="text" id="testInput">
<script type="text/javascript">
    document.getElementById('testInput').addEventListener('input', function(e){
        var value = e.target.value; //e.target指向事件执行时鼠标所点击区域的那个元素;初学者会认为当前事件所绑定的元素就是鼠标所点击的那个元素,这时就要看看时间绑定的元素内部有没有子元素,若是有e.target指向这个子元素,若是没有e.target和this都指向事件所绑定的元素
    });
</script>
复制代码

IOS键盘字母输入,默认首字母大写的解决方案

设置以下属性

<input autocapitalize="off" autocorrect="off" />
复制代码

//input的三个属性autocomplete:默认为on,表明是否让浏览器自动记录输入的值,能够在input中加入autocomplete="off"来关闭记录,保密输入内容;autocapitalize:自动大小写;autocorrect:纠错

关于iOS与OS X端字体的优化(横竖屏会出现字体加粗不一致等)问题

iOS浏览器横屏时会重置字体大小,设置text-size-adjust为none能够解决iOS上的问题,但桌面版Safari的字体缩放功能会失效,所以最佳方案是将text-size-adjust为100%

-webkit-text-size-adjust: 100%;
-ms-text-size-adjust: 100%;
text-size-adjust: 100%;
复制代码

某些状况下非可点击元素如(label,span)监听click事件,ios下不会触发

针对此种状况只需对不触发click事件的元素添加一行css代码便可

cursor: pointer;
复制代码

ios对时间date()的支持不同

var date =new Date("2019/10/21"); 
复制代码

调试发现2019/10/21等同2019-10-21 00:00:00,也就是说ios默认就是从0开始计算的,咱们不须要设置后面的时分秒为00:00:00

iOS(safari)标签绑定点击事件无效

iOS(safari)有时候某个标签绑定点击事件无效,加上空的onclick=""就行了,如:<a onclick=""></a>

ios中location.href跳转页面空白

在location.href外套一层setTimeout就解决了!

setTimeout(() => {
       window.location.href = 'www.juejin.im'
}, 0);
复制代码

键盘弹起下落时的bug解决方法

在App.vue的created钩子里统一处理便可

created() {
    this.handleFocusOut();
    this.handleResize();
},
methods:{
    handleFocusOut() {
      // input 焦点失焦后,ios 键盘收起,但没有触发 window resize,致使实际页面dom仍然被键盘顶上去--错位
      document.addEventListener('focusout', () => {
        document.body.scrollTop = 0;
      });
    },
    // 监听resize事件(键盘弹起触发),而后将 input textarea 元素滑动到可视区域,并将特定元素隐藏
    handleResize() {
      const clientHeight = document.documentElement.clientHeight;
      window.addEventListener('resize', () => {
        // 判断当前 active 的元素是否为 input 或 textarea
        if (
          document.activeElement.tagName === 'INPUT' ||
          document.activeElement.tagName === 'TEXTAREA'
        ) {
          setTimeout(() => {
            // 原生方法,滚动至须要显示的位置
            document.activeElement.scrollIntoView();
          }, 0);
        }

        // 解决键盘弹起后 fixed 定位元素被顶起问题
        const bodyHeight = document.documentElement.clientHeight;
        const ele = document.getElementById('fixed-bottom');
        if (ele) {
          if (clientHeight > bodyHeight) {
            ele.style.display = 'none';
          } else {
            ele.style.display = 'block';
          }
        }
      });
    }
}
复制代码

总结

路漫漫其修远兮,在兼容的道路上渐行渐远

相关文章
相关标签/搜索