移動端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';
          }
        }
      });
    }
}
複製代碼

總結

路漫漫其修遠兮,在兼容的道路上漸行漸遠

相關文章
相關標籤/搜索