一、什麼是點透?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的文章。