移動端tap或touch類型事件的點透問題認識

一、什麼是點透?html

舉例說明:下圖B元素是黃色方塊,B元素中包含了C元素,C元素是一個a連接,自己自帶click事件按,而後又一個半透明的粉色元素A遮蓋在B元素上(看圖中A元素是覆蓋在B元素上的,否則B元素區域應該是正黃色,如今是橙黃色,證實B上面被A覆蓋着);瀏覽器

代碼以下:app

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
    <title>Title</title>
    <style>
        *{margin:0;padding:0;}
        #div1{width:300px;height:300px;background-color:rgba(255,0,0,.25);}/*紅色半透明遮蓋層*/
        #div2{width:240px;height:240px;background-color:yellow;position:absolute;left:30px;top:30px;;z-index:-1;}/*黃色內容層B*/
        #console{border:1px solid green;position:absolute;top:300px;width:100%;}/*綠色狀態輸出框*/
    </style>
</head>
<body>
<div id="div1"></div>
<div id="div2">
    <a href="www.baidu.com">www.baidu.com</a>
</div>
<div id="console"></div>
<script>
    var div1=document.getElementById('div1');
    var div2=document.getElementById('div2');
    var con=document.getElementById('console');
    function handle(e){  /*#div1點擊的時候touchstart\touchend都會觸發這個事件,而後經過e.type判斷事件類型來區分是touchstart仍是touchend*/
        var tar= e.target,eve= e.type;
        var ele=document.createElement('p');
        ele.innerHTML='target:'+tar.id+'event:'+eve;
        con.appendChild(ele);
        if(tar.id==='div1'){
            div1.style.display='none';
        }
    }
    div1.addEventListener('touchend',handle);
    div1.addEventListener('touchstart',handle);
</script>
</body>
</html>

上面代碼點擊圖中除C區域之外的地方,固然是說A、B,都不會出現任何問題,結果以下:框架

target:div1 event:touchstart                                                      
target:div1 event:touchend                                                       

可是當你點擊元素C的時候首先A元素會消失,而後頁面會跳轉到百度首頁,按理來講A元素遮蓋住了元素B、C,可是這裏A的touchstart事件卻點透了A元素,觸發了C元素上的click事件,這就是傳說中的點透。spa

爲了更清楚的看到這個過程,咱們在B元素上也綁定一個click事件,scala

div2.addEventListener('click',handle);

點擊B區域,結果以下:code

target:div1 event:touchstart                                                           
target:div1 event:touchend                                                            
target:div2 event:click                                                                  

可見先觸發了A元素上的touchstart、touchend事件,以後又觸發了B元素上的click事件,這也是點透現象的證實。htm

二、點透現象出現的場景blog

  一、A、B兩個元素上下Z軸重合,就是上下摞一塊兒了;事件

  二、上層的A點擊後消失(這點很重要);

  三、B自己有默認click事件(如a標籤),或者B元素自己綁定了click事件;

  四、在以上狀況下,點擊A、B重疊的部分,就會出現點透現象。

三、點透產生的緣由

click延遲,延遲,仍是延遲!!!

在移動端不適用click事件,而是用touch事件代替,就是由於click事件有着明顯的延遲,具體touch和click的區別以下:

1、touchstart,在這個DOM(或冒泡到這個DOM)上手指觸摸就能觸發;
2、click,在這個DOM上手指觸摸,且手指不曾在屏幕上移動(某些瀏覽器容許一個很是小的位移值),且在這個DOM上手指離開屏幕,且觸摸和離開屏幕之間的時間間隔較短(某些瀏覽器不檢測間隔時間,也會觸發click)才能觸發。

也就是說,事件的觸發事件從早到晚爲:touchstart早於touchend,早於click,亦即click的觸發是有延遲的,這個時間大概是300ms。

因爲咱們在touchstart階段就隱藏了A元素,當click被觸發時候,可以被點擊的元素則是其下的B元素。

四、解決方案

  一、對於B元素自己沒有默認click事件的狀況下(無a標籤等),應統一使用touch事件,統一代碼風格,而且因爲click事件在移動端延遲要大不少,不利於用戶體驗,因此觸摸事件應儘可能使用touch事件。

  二、對於B元素自己存在默認click事件的狀況,應即時取消A元素的默認點擊事件,阻止click事件的產生,即給A元素綁定touchend事件,在事件中阻止默認行爲:

    

 $("#div1").on("touchend", function (event) {

     event.preventDefault();

 });

  三、針對遮蓋層使用click事件,而不是touch事件,這是由於遮蓋層的點擊有小延遲也是沒有關係的,反而會有疑似更好的用戶體驗。

五、現有解決方案框架(庫)

  一、衆所周知,zepto的tap事件存在點透現象,可是最新版的zepto已經解決了這個問題,

  二、在zepto修復問題以前,有fastclick、hammer等通用庫可使用。

本文參考了http://www.cnblogs.com/zldream1106/p/3670988.html、http://www.cnblogs.com/wqhwe/p/5630557.html的文章。

相關文章
相關標籤/搜索