移動頁面事件穿透/點擊穿透問題


一、背景

博主所負責其中一個項目是web頁面,在移動端上出現了事件穿透問題,開發介紹問題原因后,發覺是移動web一個知識點,值得記錄一下。

二、click與300ms延遲

移動瀏覽器提供一個特殊的功能:雙擊(double tap)放大

300ms的延遲就來自這里,用戶觸碰頁面之后,需要等待一段時間來判斷是不是雙擊(double tap)動作,而不是立即響應click(單擊),等待的這段時間大約是300ms。

  1. 移動端touch事件提供:touchstarttouchmovetouchend,卻沒有tap支持;
  2. 主流框架/庫都是手動實現了tap事件,以求消除300ms延遲,提高頁面響應速度
  3. 對於簡單的頁面,可以把 touchstart 或者 touchend 當作tap來用,但存在一些問題,比如手指接觸目標元素,按住不放,慢慢移出響應區域,會觸發 touchstart 事件執行對應的事件處理器(本不應該觸發),touchend 事件也存在類似的問題。
  4. 使用原生的touch事件存在點擊穿透的問題,因為click是在touch系列事件發生后大約300ms才觸發,混用touchclick肯定會導致事件穿透。
  5. 手機上響應click事件有300ms的延遲,會有響應慢/延遲的感覺,因此很多移動頁面會使用touch/tap事件。

三、tap事件

用過Zepto或者KISSY等移動端js庫的人肯定對tap事件不陌生,我們做PC頁面時候綁定click,相應地手機頁面就綁定tap。但原生的touch事件本身是沒有tap的,js庫提供的tap事件都是模擬出來的。

Zepto中對tap事件處理:如果在touched響應250ms無操作后,則觸發singleTap。即事件觸發順序為:touch-tap-click。

三、點擊穿透問題

點擊穿透現象有3種:

  • 點擊穿透問題:點擊蒙層(mask)上的關閉按鈕,蒙層消失后發現觸發了按鈕下面元素的click事件。
    • 解析:蒙層的關閉按鈕綁定的是touch事件,而按鈕下面元素綁定的是click事件。touch事件觸發之后,蒙層消失了,300ms后這個點擊的click事件fire,event的target自然就是按鈕下面的元素。
  • 跨頁面點擊穿透問題:如果按鈕下面恰好是有href屬性的a標簽,那么頁面就會發生調整。因為a標簽跳轉默認是click事件觸發。原因同上。
  • 第三種:這次沒有mask,直接點擊頁面內按鈕跳轉至新頁,然后發現新頁面中對應位置元素的click事件被觸發了。
    • 解析:和蒙層的道理一樣,js控制頁面跳轉的邏輯如果是綁定在touch事件上的,而且新頁面中對應位置的元素綁定的是click事件,而且頁面在300ms內完成了跳轉,三個條件同時滿足,就出現這種情況。

四、解決方案

思路:

  1. 不要混用touch和click:touch之后300ms會觸發click,只有touch或者只用click就自然不會存在問題。

  2. 吃掉/消費掉touch之后的click

    依舊使用tap,只是在可能發生點擊穿透的情形下做額外的處理,拿個東西來擋住、或者tap后延遲350ms再隱藏mask、pointer-events、在下面元素的事件處理器里做檢測。

我們對事件響應速度要求不高,最后是通過延遲隱藏/關閉mask/彈窗解決的,簡單可控哈。

參考:https://juejin.im/entry/56ce9c97c24aa80052101aab


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM