總結在移動端碰到的坑


一、安卓設備的select options的坑,盡量使用各瀏覽器內核都支持的api

 在添加 OPTION 元素時

  • 如果需要向指定索引前插入 OPTION,可以使用 options.add(option, index);
  • 如果需要向 SELECT 尾部添加 OPTION,可以使用 options.add(option);
  • 如果需要向指定索引處添加(或更改) OPTION,可以使用 options[index] = option。    

 在刪除 OPTION 元素時

  • 如果想刪除指定索引處的 OPTION 元素,可以使用 select.remove(index) 或 options[index] = null;
  • 如果想刪除某個指定的 OPTION 元素,可以使用 select.remove(option);
  • 如果想刪除 SELECT 中所有 OPTION,可以使用 select.length = 0 或 options.length = 0。

二、移動端click事件300ms延遲

 click事件,在移動端,會經過300ms的延遲后才觸發。原因是,移動瀏覽器提供一個特殊的功能:雙擊(double tap)放大,用戶碰觸頁面之后,需要等待一段時間來判斷是不是雙擊(double tap)動作,而不是立即響應單擊(click),等待的這段時間大約是300ms。那么怎么消除這個300ms延遲呢?

 1.使用fastclick插件,會消除所有click事件的延遲,不推薦使用插件來解決這個問題

 2.不用click事件,用移動設備提供的原生touch事件,或某些移動端手勢庫提供的tap事件。移動端touch事件提供了 touchstart 、 touchmove 、 touchend等,對於簡單的頁面,可以把 touchstart 或者 touchend 當作tap來用,這樣可以解決300ms延遲問題,但並不完美,比如手指接觸目標元素,按住不放,慢慢移出響應區域,依然會觸發 touchstart事件對應的事件處理器(本不應該觸發),touchend也有類似的問題,所以,如果想模擬原生App的點擊事件,需要自己封裝一套tap事件,或者使用手勢庫的tap事件,tap事件原理也非常簡單,是由touchstart和touchend組合而成,首先要判斷touchend和touchstart的偏移距離,然后阻止掉touchend事件300ms之后觸發的click事件,並且始終以touchend事件作為觸發的必要條件,下面是個demo:

function tap(node,callback,scope) {
        node.addEventListener(TOUCHSTART, function(e) {
            x = e.touches[0].pageX;
            y = e.touches[0].pageY;
        });
        node.addEventListener(TOUCHEND, function(e) {
            e.stopPropagation();
            e.preventDefault();
            var curx = e.changedTouches[0].pageX;
            var cury = e.changedTouches[0].pageY;
            if (Math.abs(curx - x) < 6 && Math.abs(cury - y) < 6) {
                callback.apply(scope, arguments);
            }
        });
}

下面是zepto的tap事件實現源碼:

if (deltaX < 30 && deltaY < 30) {
  tapTimeout = setTimeout(function() {
    var event = $.Event('tap')
    event.cancelTouch = cancelAll
    touch.el.trigger(event)

    if (touch.isDoubleTap) {
      if (touch.el) touch.el.trigger('doubleTap')
      touch = {}
    }else {
      touchTimeout = setTimeout(function() {
        touchTimeout = null
        if (touch.el) touch.el.trigger('singleTap')
        touch = {}
      }, 250)
    }
  }, 0);
}

三、點擊穿透

   如果某個返回按鈕的位置,恰好在要返回的這個頁面的帶有href屬性的a標簽的范圍內,在點擊返回按鈕后,頁面快速切換到有a標簽的頁面,300ms后觸發了click事件,從而觸發了a標簽的意外跳轉,這個就是典型的點擊穿透問題。罪魁禍首其實就是a標簽跳轉默認是click事件觸發,而移動端的touch事件觸發之后,依然會在300ms后觸發click事件。解決辦法其實在上面一條已經提到了。

 1.就是消費掉touch事件完成后的click事件。

 2.不要混用touch和click事件。顯然不可能都綁定click事件,因為要解決300ms延遲問題(除了fastclick),那么只能都綁定touch事件,這樣click事件永遠不會被觸發。

 綜上二條,最好的辦法就是自己封裝一個tap事件,並且自己阻止掉300ms后的click事件,完美解決。

 注意:zepto並沒有阻止click事件,所以使用zepto的tap事件依然會導致點擊穿透問題,你需要手動添加 e.preventDefault() 來阻止click事件。

四、移動端整體布局

   移動端的整體布局一般來說可以分為上中下三個部分,分別為 header、main、footer,其中header、footer 是固定高度,分別固定在頁面頂部和頁面底部,而 main 是頁面展示主體內容的部分,並且可以滾動。要實現這種布局,有兩種辦法:

 1.最容易想到的就是header和footer為fixed,body最小高度為一屏,超出則滾動。這種布局有個優點,在ios的safari上頁面的地址欄會隨着 body 的滾動隱藏起來,缺點就是fixed在有input的頁面會有各種兼容性問題(經測試,在固定到主屏幕並且去掉導航欄的情況下fixed有bug,移動端的各種瀏覽器中是沒有問題的)

 2.采取內滑的策略。具體的實現方式可能略有不同,但思路都是在元素內部滾動,而不是body。比如可以設置header和footer為absolute,main也為absolute,並且overflow-y為auto,或者用彈性布局的方式。在移動端元素內滑動會有不流暢的問題,建議加上-webkit-overflow-scrolling: touch,這樣就能愉快的滾動了。這種布局的優點就是避免了使用fixed,缺點就是移動端瀏覽器中input框的光標閃爍問題(在滾動頁面的時候,光標會錯位,不跟隨input框閃爍,原因是加了-webkit-overflow-scrollingtouch,導致滑動速度太快來不及重繪,解決方法是在你滑動頁面的時候直接讓input失去焦點,隱藏光標

五、input 的 compositionstart 和 compositionend 事件

   在input中輸入中文的時候,在沒有選定文字前,輸入的每一個拼音字母也會觸發input事件,這顯然不是我們想要的。我們需要 compositionstart 和 compositionend 事件來處理這個問題。compositionstart會在用戶開始進行非直接輸入的時候觸發,compositionend會在點選候選詞或者點擊「選定」按鈕之后觸發。我們可以在compositionstart的時候將input事件上鎖,讓其不執行,在compositionend的時候再解鎖,注意:compositionend 事件是在 input 事件后觸發的。

六、移動端 1px border 實現

 由於設備高分辨率屏的原因,邏輯像素的 1px 的 border 在移動設備上會用兩個或三個物理像素來表示,所以看起來會感覺很粗。解決方案有很多,但兼容性最好的方案是用偽元素的 box-shadow 或 border 實現 border,然后用 transform: scale(.5) 縮小到原來的一半。具體如下:

.block {
      width: 100px;
      height: 100px;
      margin: 10px;
      position: relative;
      /*border: 1px solid red;*/
}
.block:before {
      content: '';
      position: absolute;
      transform-origin: 0 0;
      top: 0;
      left: 0;
      width: 200%;
      height: 200%;
      border: 1px solid red;
      transform: scale(.5);
}

七、一些小坑

 1.format-detection

<meta name="format-detection" content="telephone=no">

 默認情況下,設備會自動識別任何可能是電話號碼的字符串。設置telephone=no可以禁用這項功能。

 2.禁止復制、選中文本

 user-select: none;

 3.長時間按住頁面出現閃退或禁止 iOS 彈出各種操作窗口

 -webkit-touch-callout: none;

 4.ios或安卓設備input等元素的特殊樣式

 -webkit-appearance: none;

 5.ios或android下觸摸元素時出現半透明灰色遮罩

 -webkit-tap-highlight-color:rgba(255,255,255,0)

 6.移動端偽類 :active 不起作用

   document.addEventListener('touchstart',function(){},false);

 7.啟用硬件加速使動畫更流暢

 transform: translate3d(0, 0, 0);

 8.旋轉屏幕時,字體大小調整的問題

 -webkit-text-size-adjust:100%;

 9.transition閃屏

 設置子元素以3D的方式呈現

 -webkit-transform-style: preserve-3d;

 設置進行轉換的元素的背面在面對用戶時是否可見

 -webkit-backface-visibility:hidden;

 10.CSS3 rotateY transition 在safari上有bug

 當前轉動的元素,在其上有元素覆蓋它時,或在其下有元素被它覆蓋時,會出現如下bug:

 

 建議設置transform: translateZ(-1000px);

 11.移動端選擇相片

 <input type=file accept="image/*">

 一定要顯示的聲明accept接收的類型

 

 

參考文獻:http://www.cnblogs.com/strick/p/5161660.html

     https://zhuanlan.zhihu.com/p/26141351

     https://zhuanlan.zhihu.com/p/24837233

     http://www.cnblogs.com/wangpenghui522/p/5398137.html

     http://www.cnblogs.com/liulinjie/p/5776337.html

     http://www.haorooms.com/post/phone_web

     http://stackoverflow.com/questions/20737503/mobile-safari-input-caret-does-not-scroll-along-with-overflow-scrolling-touch

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM