一、點透出現的場景
1.A/B兩個層上下z軸重疊。
2.上層的A點擊后消失或移開。(這一點很重要)
3.B元素本身有默認click事件(如a標簽) 或 B綁定了click事件。
在以上情況下,點擊A/B重疊的部分,就會出現點透的現象。
二、為什么會出現點透
click延遲,延遲,還是延遲。
在移動端不使用click而用touch事件代替觸摸是因為click事件有著明顯的延遲,具體touchstart與click的區別如下:
1.touchstart:在這個DOM(或冒泡到這個DOM)上手指觸摸開始即能立即觸發
2.click:在這個DOM(或冒泡到這個DOM)上手指觸摸開始,且手指未曾在屏幕上移動(某些瀏覽器允許移動一個非常小的位移值),且在這個在這個dom上手指離開屏幕,且觸摸和離開屏幕之間的間隔時間較短(某些瀏覽器不檢測間隔時間,也會觸發click)才能觸發
也就是說,事件的觸發時間按由早到晚排列為:touchstart 早于 touchend 早于 click。亦即click的觸發是有延遲的,這個時間大概在300ms左右。移動瀏覽器為什么會設置300毫秒的等待時間呢?這與雙擊縮放的方案有關。平時我們有可能已經注意到了,雙擊縮放,即用手指在屏幕上快速點擊兩次,可以看到內容或者圖片放大,再次雙擊,瀏覽器會將網頁縮放至原始比例。
瀏覽器捕獲第一次單擊后,會先等待一段時間,如果在這段時間區間里用戶未進行下一次點擊,則瀏覽器會做單擊事件的處理。如果這段時間里用戶進行了第二次單擊操作,則瀏覽器會做雙擊事件處理。這段時間就是上面提到的300毫秒延遲。
由于我們在touchstart階段就已經隱藏了罩層A,當click被觸發時候,能夠被點擊的元素則是其下的B元素,根據click事件的觸發規則:
只有在被觸發時,當前有click事件的元素顯示,且在面朝用戶的最前端時,才觸發click事件。
由于B綁定了click事件(或者B本身默認存在click事件),所以B的click事件被觸發,產生了點透的情況。
二、解決方案
1.對于B元素本身沒有默認click事件的情況(無a標簽等),應統一使用touch事件,統一代碼風格,并且由于click事件在移動端的延遲要大很多,不利于用戶體驗,所以關于觸摸事件應盡量使用touch相關事件。
2.對于B元素本身存在默認click事件的情況,應及時取消A元素的默認點擊事件,從而阻止click事件的產生。即應在上例的 handle函數中添加 代碼如下:
if(eve == "touchsend") e.preventDefault();
3.對于遮蓋浮層,由于遮蓋浮層的點擊即使有小延遲也是沒有關系的,反而會有疑似更好的用戶體驗,所以這種情況,可以針對遮蓋浮層自己采用click事件,這樣就不會出現點透問題。
四、現有解決方案框架(庫)
眾所周知,zepto的tap事件是有點透問題的,但是最新版的zepto已經修復了這個問題。
-
在zepto修復問題之前,有fastclick、hammer等通用庫可以使用。
FastClick 是 FT Labs 專門為解決移動端瀏覽器 300 毫秒點擊延遲問題所開發的一個輕量級的庫。簡而言之,FastClick 在檢測到touchend事件的時候,會通過 DOM 自定義事件立即觸發一個模擬click事件,并把瀏覽器在 300 毫秒之后真正觸發的click事件阻止掉。使用方法如下。
第一步:在頁面中引入fastclick.js文件。第二步:在js文件中添加以下代碼
在 window load 事件之后,在body上調用FastClick.attach()即可。
window.addEventListener(function(){
FastClick.attach( document.body );
},false );
如果你項目使用了JQuery,就將上面的代碼改寫成:
$(function() {
FastClick.attach(document.body);
});
3.靜止縮放
<meta name="viewport" content="width=device-width user-scalable= 'no'">
使用這個方法必須完全禁用縮放來達到目的,雖然大部分移動端能解決這個延遲問題,但是部分蘋果手機還是不行。