在PC端上的JS事件相信大家已經熟悉不少,諸如click\mouseover這類事件,都可以滿足互動的需要,雖然移動端上的事件可能平常稍有接觸,但是可能不太瞭解其中具體的用法區別。
前言:
這幾個事件最早出現於IOS safari中,為了向開發人員轉達一些特殊的資訊,所以新增了這些事件,隨著Android中的webkit的加入,慢慢地這樣的專有事件成了事實的標準,從而導致W3C開始指定Touch Event規範的內容。
具體說來有這樣幾個事件:
- touchstart 手指觸控螢幕時觸發,即使已經有手指在螢幕上也會觸發。
- touchmove 手指在螢幕滑動時觸發。
- touchend 手指從螢幕時移開時觸發。
事件定義的方式:
大致上分為DOM0事件和DOM2事件兩種.
DMO0事件,就是傳統的直接將事件作為屬性設定的形式:
div1.ontouchstart = function(){
alert(1);
}複製程式碼
DOM2事件,則是用addEventListener的方式來繫結事件處理程式:
div1.addEventListener("touchstart",function(){
alert(1);
});
複製程式碼
大多數時候不推崇第一種方式,這種方式在移動端使用時好時壞,不建議使用。
PC的事件比移動端上的事件響應的慢300ms:
在早期的手機上,瀏覽器為了能夠實現放大和縮放功能,採用雙擊的方式來達到這樣的互動效果,為了實現這樣的效果,瀏覽器需要判斷使用者在第一次觸碰螢幕之後,是否在300ms之內再次點選,有則表明使用者希望縮放和放大,所以click事件會推遲到300ms之後執行。
var div = document.querySelector("#div");
div.onclick = function(){
console.log("click!");
} div.ontouchstart = function(){
console.log("touchstart!");
}複製程式碼
可以看到每次點選,touchstart總會先於click事件執行。當然這方面的問題有專門的庫用於解決延遲的問題。諸如:Fastclick
點選穿透問題:
這個問題在當有一個絕對定位或固定定位元素繫結了touch事件,那麼覆蓋在他之下的具有點選特性的元素也會被觸發。
比如:有一個遮罩層A元素,他的底下有一個連結元素B.當這個遮罩層點選之後希望遮罩層消失,真實的狀況是這時候點選遮罩層不見的同時會跳轉頁面。複製程式碼
這是為什麼? 前面說過了touchstart會先於click事件執行,當上述的這個遮罩層消失在300ms之內消失時,那麼他底下的具有點選特性的元素會被觸發。大家可以私下模擬上述的例子。
如何解決?
下層元素不使用點選特性的元素
我可以去某寶的移動版網站上看,他首頁使用的多層的DIV來代替A標籤
這種方法不太推薦,因為a標籤能夠為SEO提供一些資訊
阻止所有點選:
document.addEventListener("click",function(ev){
ev.preventDefault();
})document.addEventListener("touchstart",function(ev){
ev.preventDefault();
})複製程式碼
這時候的有點選特性的元素的互動行為將會失效,當然也可以根據實際需要重新開啟互動行為。
程式碼如下:
a.ontouchstart = function(){
window.location = this.href;
}複製程式碼
這樣既兼顧了SEO又可以安然使用點選事件。當然它還有其他的好處。
- 能夠阻止IOS10縮放:對於ISO10設定meta標籤禁止縮放是沒有作用的,上面的程式碼阻止了瀏覽器的預設行為。
- 阻止IOS10下回彈效果
- 去除系統滾動條
- 禁止長按選中文字和圖片:當然也同時阻止了input獲取焦點的行為,這就需要使用單獨為input新增一個阻止冒泡的行為。以免事件冒泡至頂層元素而被阻止互動行為。
input.ontouchstart = function(ev){
ev.stopPropagation();
}複製程式碼
移動端事件物件:
注意到前面的例子裡每一個事件處理程式都有一個evt的引數了嗎,那是有關於當前觸控的相關資訊,通過這樣一個物件,能夠獲取到當前觸碰的座標,觸碰的手指個數等等。其中最重要的常用的莫過於手指列表了。
touches:當前位於螢幕下的手指列表資訊targetTouches: 當前位於當前元素下的手指列表資訊changedTouches: 當前涉及到當前事件的手指列表複製程式碼
這三個手指列表都存在觸碰事件物件裡面,在每次發生觸碰之後這裡的列表都會更新。
var div = document.querySelector("#div");
div.ontouchmove = function(evt){
this.innerHTML = ` touches-length:${evt.touches.length
} targetTouches-length:${evt.targetTouches.length
} changedTouches-length:${evt.changedTouches.length
} ` console.log(evt);
}複製程式碼
以上例項,在手指移動於DIV上之後會更新DIV的內容。分別展示了touches、targetTouches、changedTouches的手指個數
感謝閱讀!希望能共同進步!