touchstart與click不得不說的故事

歡迎關注富途web開發團隊 ,缺人從衆css

有一次給公司作了個自適應的的費用介紹頁,主要是關於收費標準的調整,老闆表示很重視,適用人羣也不少,因此也反饋獲得幾個不常遇到的問題,其中一個就是關於touchstartclick事件的問題。這裏記錄一下,歡迎指正。前端

1. 問題

某天中午,開發了好幾天的費用介紹頁終於上線了。運營同窗滿懷信心地發送了收費標準頁面的推廣消息,而後咱們都瀟灑地吃午餐去了。正吃着午餐的時候,收到微信羣中某客戶的反饋:咱們的頁面最關鍵的地方——收費詳情點擊沒有反應!android

頁面點擊無反應

隨後咱們查看了前端錯誤上報和日誌,沒有任何線索。與客戶確認環境,客戶使用的是 windows PC 。web

但奇怪的是,我測試了多臺設備,仍然沒法重現問題。在同事的機器上也沒能復現這個問題。windows

2. 溯源

咱們從新審視了一遍事件綁定的代碼,發現其實很是簡單。bash

var tap = 'ontouchstart' in window ? 'touchstart' : 'click';
wrap.addEvenListener(tap, function(){
    signUp();
});
複製代碼

惟一有點特殊的就是咱們的頁面是自適應的,爲了不移動端點擊 300ms 延遲,在綁定前作了一下判斷,移動端綁定了touchstart事件,PC 端綁定了click事件。然而這段代碼看起來也是人畜無害,並不至於致使點擊沒有反應。微信

3. 定位

咱們再次詢問了客戶更詳細的環境信息,得到了一個很是關鍵的信息,客戶使用的是聯想的筆記本。因爲在 surface 出來的時候組裏有同事關注過,想起來當時聯想也出了不少觸屏筆記本。因而和客戶再次聯繫,確認了他使用的就是聯想的觸屏筆記本。iphone

至此問題就很是明確了,問題最終仍是定位在綁定的「點擊」事件上。咱們在檢測時只是粗暴地檢測了設備是否支持觸控事件,卻忽略了支持觸控事件的仍然多是 PC 設備,客戶仍然可能經過點擊鼠標來進行操做。這實際上反映出咱們忽略了用戶設備的多樣性,開發的時候對用戶設備作了太多的假設,最終致使咱們覺得它是一臺手機,結果它是一臺貨真價實的筆記本電腦。函數

概括起來,關鍵的點就是:測試

  • 有些 PC 設備屏幕爲觸摸屏,同時支持touchstartclick事件;
  • 用戶觸發touchstart事件,默認必然會致使觸發click事件,可是觸發click事件,不必定會致使touchstart事件被觸發;
  • 此類設備外接鼠標時,經過上面的綁定方式,會綁定touchstart事件,可是鼠標操做只能觸發click,致使touchstart不觸發;

4. 解決辦法

至此,問題的緣由已經分析完畢,如何應對又成了一個問題。這個問題的關鍵在於肯定不一樣設備上使用「點擊」事件的策略。大體分爲以下幾種:

1. 均使用click事件

  • 優勢:自適應時,不一樣設備均支持,沒有兼容性問題,開發成本低;
  • 缺點:移動端存在300ms的延遲問題(雖然同事表示通常感受不出來)

2. 經過UA判斷設備是否爲移動端,再確認事件類型

function isMobile() {
    return navigator.userAgent.match(/(blackberry|configuration\/cldc|hp |hp-|htc |htc_|htc-|iemobile|kindle|midp|mmp|motorola|mobile|nokia|opera mini|opera |Googlebot-Mobile|YahooSeeker\/M1A1-R2D2|android|iphone|ipod|mobi|palm|palmos|pocket|portalmmm|ppc;|smartphone|sonyericsson|sqh|spv|symbian|treo|up.browser|up.link|vodafone|windows ce|xda |xda_)/i) ? true : false;
}
 var tap = isMobile() ? 'touchstart' : 'click';
複製代碼
  • 優勢:自適應時,開發成本低,經過設備類型肯定點擊事件類型,能知足絕大部分問題,用戶操做也比較符合預期;
  • 缺點:不能知足全部狀況,若是用戶給 iPad 或者 Android 手機(認定爲移動設備)外接鼠標進行操做,這種方式就不起做用(PS:你非要這麼作,我也無FUCK說)。

3. 所有使用click,經過FastClick解決300毫秒的延遲問題

//引入FastClick
var FastClick = require('tool-fastclick');
//頁面初始化時調用
new FastClick(document.body);
複製代碼
  • 優勢:開發成本低也比較低,也不會出現1,2中問題
  • 缺點:額外引入三方庫,FastClick 是否會有其餘的坑?這點不能保證

注:tool-fastclick是組內 fork 的 FastClick 版本,目前沒有開源。咱們對其中存在的問題進行了一部分修復,好比:同個頁面有多個 select 框選擇時,會跳選項的 bug 。

4. 萬全之策

其實最好的方案是不要在綁定的時候進行判斷,而是對touchstartclick同時綁定,可是在touchstart觸發的時候暫時取消後續 click 的響應。

具體的實施方式有三種:

  1. touchstart事件響應中調用preventDefault()方法,阻止後續click事件的觸發
  2. touchstart事件中設置一些標記,或者取消click事件的綁定,使得click事件觸發時不會觸發咱們綁定的邏輯,在一段時間(例如300-500ms)後再恢復
  3. 直接對事件處理函數進行節流(throttle),保證在一段時間內(300ms - 500ms),事件處理函數只觸發一次

固然,和上面同樣,每種方案都有利弊。

方案1取消了後續click事件的觸發,在多個事件綁定疊加或者多人合做的時候,有可能致使一些依賴click事件的邏輯出現bug。

方案2和方案3的原理基本同樣,實施起來有必定的複雜度,並且本質上屬於 hack 的方案,應對一些很是規場景時就不適用了。好比須要快速連續點擊的場景,或者用戶點擊很是慢的場景等等。

總之,沒有萬全之策,呵呵……

最後

有人可能會對文章最前提到的收費介紹頁比較感興趣,來了,看這裏

相關文章
相關標籤/搜索