什么是click點(diǎn)透?
核心代碼:
<div class="content">
<div id="underLayer">
<a href="www.baidu.com">鏈接</a>
<input type="text" class="text1" >
<input type="select" class="select">
<input type="radio" class="select">
<input type="checkbox" class="select">
<button class="btn" id="openPopup">彈出</button>
</div>
<div id="popupLayer">
<div class="layer-title">彈出層</div>
<div class="layer-action">
<button class="btn" id="closePopup">關(guān)閉</button>
</div>
</div>
</div>
<script type="text/javascript">
var oPop =document.getElementById('popupLayer');
var oUn = document.getElementById('underLayer');
var oOpen = document.getElementById('openPopup');
oPop.addEventListener('touchend', function(e){
this.style.display='none';
});
oUn.addEventListener('click',
function(){
alert('1');
} );
</script>
點(diǎn)擊彈出層,touch事件首先被觸發(fā),彈出層和遮罩就被隱藏了。touchend后繼續(xù)等待300ms發(fā)現(xiàn)沒有其他行為了,則繼續(xù)觸發(fā)click,由于這時彈出層已經(jīng)消失,所以當(dāng)前click事件的target就在底層元素上,于是就alert內(nèi)容。整個事件觸發(fā)過程為 touchend -> click。
而由于click事件的滯后性(300ms),在這300ms內(nèi)上層元素隱藏或消失了,下層同樣位置的DOM元素觸發(fā)了click事件(如果是input框則會觸發(fā)focus事件,如果是<a>鏈接則會進(jìn)行頁面跳轉(zhuǎn),或是 select / radio / checkbox都會被觸發(fā)),看起來就像點(diǎn)擊的target“穿透”到下層去了。這就是點(diǎn)透現(xiàn)象
解決方法:
a、阻止默認(rèn)事件 e.preventDefault() 給touchend事
件加上 e.preventDefault()
oPop.addEventListener('touchend', function(e){
this.style.display='none';
e.preventDefault();
});
b、利用css3屬性 pointer-events
取值auto|none
當(dāng)取值為auto 時,效果和沒有定義 pointer-events 屬性相同,鼠標(biāo)不會穿透當(dāng)前層。
當(dāng)取值為none 時,元素不再是鼠標(biāo)事件的目標(biāo),鼠標(biāo)不再監(jiān)聽當(dāng)前層而去監(jiān)聽下面的層中的元素。但是如果它的子元素設(shè)置了pointer-events為其它值,比如auto,鼠標(biāo)還是會監(jiān)聽這個子元素的。
詳細(xì)代碼:
oPop.addEventListener('touchend', function(e){
this.style.display='none';
oUn.style.pointerEvents='none';
setTimeout(function(){
oUn.style.pointerEvents='auto';
}, 400);
});
c. 遮擋
由于 click 事件的滯后性,在這段時間內(nèi)原來點(diǎn)擊的元素消失了,于是便“穿透”了。因此我們順著這個思路就想到,可以給元素的消失做一個fade效果,類似jQuery里的fadeOut,并設(shè)置動畫duration大于300ms,這樣當(dāng)延遲的 click 觸發(fā)時,就不會“穿透”到下方的元素了。
同樣的道理,不用延時動畫,我們還可以在觸摸位置放一個透明的元素,這樣當(dāng)上層元素消失而延遲的click來到時,它點(diǎn)擊到的是那個透明的元素,也不會“穿透”到底下。在一定的timeout后再將生成的透明元素隱藏。代碼如下:
oPop.addEventListener('touchend', function(e){
oBg.style.display ='block';
this.style.display='none';
// 解決方法三
setTimeout(function(){
oBg.style.display='none'
}, 400);
});
參考徹底理解和解決移動WEB開發(fā)中CLICK點(diǎn)透問題