穿透現(xiàn)象與click的延遲解決方法是分不開的捶闸,若要了解穿透現(xiàn)象,需要先了解click延遲的解決原理。
移動(dòng)端click事件300ms的延遲現(xiàn)象的原因:
在最早iphone的safar瀏覽器中,為了實(shí)現(xiàn)觸屏中雙擊放大效果,當(dāng)用戶點(diǎn)擊屏幕時(shí)后會(huì)判斷在300ms內(nèi)是否有第二次點(diǎn)擊暴备,如果有,就理解成雙擊们豌,若沒有就是單擊, 就會(huì)觸發(fā)click事件.
當(dāng)你點(diǎn)擊移動(dòng)設(shè)備的屏幕時(shí),?可以分解成多個(gè)事件涯捻,順序依次為:touchstart — touchmove — touchend — click, 這些事件是按順序依次觸發(fā)的.
解決延遲的思路:
touchstart touchend是沒有延遲的,可以在touchend時(shí)觸發(fā)用戶想要在click時(shí)觸發(fā)的事件.
zepto 解決click延遲的原理:
自定義tap事件玛痊,當(dāng)用戶點(diǎn)擊元素時(shí)汰瘫,touchend事件先發(fā)生, 當(dāng)touchend事件冒泡到document時(shí)觸發(fā)目標(biāo)元素綁定的tap事件
簡(jiǎn)單模擬zepto tap的實(shí)現(xiàn)方式(這里忽略touchstart與touchend的點(diǎn)擊位置的判斷):
// document元素上綁定touchend事件, 在touchend的事件處理函數(shù)中自定義tap事件, 當(dāng)點(diǎn)擊的目標(biāo)元素的touchend事件冒泡到document上時(shí), 觸發(fā)綁定在目標(biāo)元素上的tap事件
document.addEventListener('touchend', function(e) {
// 自定義tap事件
var evt = document.createEvent('Event');
evt.init(’tap’, true, true);
// 觸發(fā)綁定在目標(biāo)元素上的tap事件
e.target.dispatch(evt);
}, false);
---------------------------------------------------------------------------------------------------------
// 用戶綁定tap事件
document.getElementById(‘elementid’).addEventListener('tap’, function(e) {
// click事件邏輯
}, false);
zepto的tap穿透現(xiàn)象:
遮罩層中有一個(gè)標(biāo)簽綁定了tap事件,觸發(fā)時(shí)遮罩層消失擂煞,該標(biāo)簽正下方有一個(gè)綁定了click的按鈕混弥,此時(shí)點(diǎn)擊上層的標(biāo)簽,同時(shí)也會(huì)觸發(fā)下層元素的click事件对省,出現(xiàn)穿透的現(xiàn)象蝗拿。
為什么會(huì)出現(xiàn)穿透:
結(jié)合前面tap事件的原理來(lái)分析:
當(dāng)觸發(fā)tap事件,上層遮罩層關(guān)閉后蒿涎,此時(shí)事件只進(jìn)行到touchend哀托,而click是在大概300ms后才觸發(fā),當(dāng)click觸發(fā)時(shí)劳秋,上面的遮罩層已消失仓手,就相當(dāng)于點(diǎn)擊到了下層的元素。
下層什么樣的元素才會(huì)形成穿透:
根據(jù)原理來(lái)說玻淑,因?yàn)榇┩甘前l(fā)生在click發(fā)生時(shí)嗽冒,也就是下層綁定了click事件或click時(shí)會(huì)觸發(fā)的事件(focus focusout)的元素,或點(diǎn)擊時(shí)有默認(rèn)形為的標(biāo)簽元素补履,如a input(會(huì)出系統(tǒng)鍵盤的type類型或綁定了focus事件)等添坊。
如何解決穿透:
方法一:直接將上層元素的tap事件換成click事件(會(huì)出現(xiàn)300ms的延遲觸發(fā)事件)
方法二:在click事件觸發(fā)前阻止它,如在touchend的事件中使用e.preventDefault()來(lái)阻止后續(xù)的click事件
zepto為何不使用e.preventDefault()來(lái)解決穿透問題箫锤?
因?yàn)閦epto的tap事件統(tǒng)一是在document的touchend時(shí)觸發(fā)的贬蛙,若在這里使用e.preventDefault()雨女,那頁(yè)面上所有元素在touchend后觸發(fā)的事件都不會(huì)被執(zhí)行了。