說說移動端web開發中的點擊穿透問題

最近一直在忙於一個無線端的項目,因爲以前主要工做都是在桌面端,移動端接觸的比較少,因此中間遇到了不少的坑,作一個簡單的記錄。segmentfault

問題背景

需求中有這樣的一個功能,點擊取件信息的時候會彈出一個地址列表的浮層,用戶選擇地址以後會將具體的地址回填到取件信息當中去。按道理講,這是一個很是簡單的功能,但是在開發過程當中卻遇到了不少很是詭異的事情。瀏覽器

初始的代碼是這麼寫的:post

var pickupInfo = $("#pickupInfo");  
pickupInfo.on("tap", function () {
    var addressList = $("#addressList");
    addressList.show();
});  

window.addEventListener("message", function () {
    // 回填地址信息
});
// addressList 是一個浮層
$("#addressList li").on("click", function () {
    // 此處回填地址到取件信息中去  
    // 具體方式則是經過iframe的postMessage發送消息,pickupInfo那邊接收消息後填充
});

爲了更清楚的說明問題,此處刪除了不少的業務邏輯。測試

在測試過程當中就發現了一個詭異的問題,在點擊pickupInfo的時候,addressList浮層閃了一下就消失了,彈出addressList浮層後當即回填了地址信息。優化

由於一開始也沒有太注意觀察,跟代碼的過程當中發現只要浮層一彈出,pickupInfo那邊就當即收到了message事件信息。當時第一反應感受是地址列表那邊出了問題,看了好幾遍代碼,一直沒發現哪裏有問題,也跟了幾回,每次都是地址列表一彈出就當即觸發了click事件。google

奇了個怪了!code

點擊穿透

試着描述了下問題google了一把,多是描述的不太準確,啥也沒搜着。沒辦法了,瞪大眼睛再操做一遍。這時候奇蹟出現了,我發現每次點擊pickupInfo,都在選中addressList中相對於屏幕與pickupInfo相同位置的地址。事件

查看了下事發地點的代碼,而後在google中敲下了這幾個字「移動端 tap」,一大堆的結果,看了幾篇文章,終於找到了問題的答案。開發

先說說touch事件吧。get

咱們知道,PC上有鼠標事件,一次點擊能夠拆分紅mousedown > click > mouseup 三步。移動端沒有鼠標,可是有相似的觸摸事件,用戶的一次點擊能夠分爲touchstart > touchmove > touchend。 雖然手機上沒有mouse事件,可是手機依然能夠響應mouse事件,爲何呢?是經過touch事件來模擬的。有人曾經對比測試過手機上和PC上的mouse事件,發現手機上的mouse要慢一些,大概在300m左右。

再說說tap事件。

在PC端,咱們常常使用到click事件,對應到移動端,咱們使用tap事件。但原生的touch事件自己是沒有tap的,也是經過模擬產生的。在Zepto中,若是在touchend事件響應250ms無操做後,會觸發singleTap事件。

// trigger single tap after 250ms of inactivity
else {
    touchTimeout = setTimeout(function(){
        touchTimeout = null
        if (touch.el) touch.el.trigger('singleTap')
        touch = {}
    }, 250)
}

至此,點擊穿透的緣由就明瞭了。

當pickupInfo監聽的tap事件獲得響應以後,會當即彈出addressList浮層,此時瀏覽器還會觸發click事件,而此時原來的pickupInfo已經徹底被addressList遮罩,因此click事件就被觸發在了與pickupInfo相同位置的addressList中對應的區域,也就正好響應了addressList中監聽的click事件。

世事奈何如此之巧~

解決方案

問題清楚了,修改方法也就明確了,因爲項目還在開發中,我的以爲當前的方案還不是特別好,後續優化後再貼出來。這裏貼篇文章,也來講說touch事件與點擊穿透問題,裏面對touch和tap事件作了詳細的說明,對點擊穿透問題也提到了幾個方案,能夠參考。

小結

這兩天一直在忙於趕開發進度,對於過程當中遇到的一些典型的問題作一些記錄,算是一種沉澱吧~~

相關文章
相關標籤/搜索