一、安卓設備的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-scrolling: touch,導致滑動速度太快來不及重繪,解決方法是在你滑動頁面的時候直接讓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