最近一直在忙於一個無線端的項目,因爲以前主要工做都是在桌面端,移動端接觸的比較少,因此中間遇到了不少的坑,作一個簡單的記錄。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事件作了詳細的說明,對點擊穿透問題也提到了幾個方案,能夠參考。
這兩天一直在忙於趕開發進度,對於過程當中遇到的一些典型的問題作一些記錄,算是一種沉澱吧~~