Vue.js 移動端 Web App 點擊穿透問題解決方案

描述

在近期的一個移動端項目中,有一個頁面須要有彈框提示,而且這個彈框經過關閉按鈕關閉。頁面當中使用了 iScroll 來實現頁面局部滾動,在 iScroll 的配置當中把 tapclick 事件都開啓了。
代碼以下:javascript

this.myScroll = new IScroll(this.$refs.wrapper, {
  mouseWheel: true,
  click: true,
  tap: true
})

在實現過程當中,遇到了一個奇怪的問題,因爲按鈕的位置與彈框右上角的關閉按鈕位置一致,當我點擊按鈕時,彈框一閃而過。html

效果以下:
效果圖vue

緣由

什麼是點擊穿透?

假如頁面上有兩個元素A和B。B元素在A元素之上。咱們在B元素的touchstart事件上註冊了一個回調函數,該回調函數的做用是隱藏B元素。咱們發現,當咱們點擊B元素,B元素被隱藏了,隨後,A元素觸發了click事件。java

經過上網查找有關資料,翻閱了移動端的書籍,發如今手機端中,事件的觸發順序爲:touchstart -> touchmove -> touchend,而 click 事件有 300ms 的延遲,當 touchstart 事件把B元素隱藏以後,隔了300ms,瀏覽器觸發了 click 事件,可是此時B元素不見了,因此該事件被派發到了A元素身上。若是A元素是一個連接,那此時頁面就會意外地跳轉。git

解決方案

1. 改用 touch 事件

因爲項目使用的是 Vue.js,這裏就提供一下 Vue.js 的解決方法。使用了 vue-tap 的一個插件,具體使用方法參看官方文檔,在須要點擊事件的時候,經過 v-tap 指令來綁定。github

// main.js
import vueTap from 'v-tap' // 引入插件
Vue.use(vueTap) // 全局註冊
v-tap="{methods:showReceiveModel}" // 在元素上綁定事件

2. 使用 fastclick 插件

這個也是在網上看到的,也能夠解決點透問題,使用方法能夠看 fastclick 的文檔,在這裏提供一下 Vue.js 的引入及使用segmentfault

import FastClick from 'fastclick'; // 引入插件
FastClick.attach(document.body, options); // 使用 fastclick

最終沒有使用這個方案是由於有一些小 bug ,如 Fastclick 致使click事件觸發兩次的問題瀏覽器

其餘

tap 一詞

對於 tap 這個詞,用過 ZeptoKISSY 等移動端js庫的人確定對tap事件不陌生,作PC頁面時綁定 click,相應地手機頁面就綁定 tap。但原生的 touch 事件自己是沒有 tap 的,js庫裏提供的tap事件都是模擬出來的。網絡

手機上響應 click 事件會有300ms的延遲,那麼這300ms究竟是幹嗎了?瀏覽器在 touchend 後會等待約300ms,緣由是判斷用戶是否有雙擊(double tap)行爲。若是沒有 tap 行爲,則觸發 click 事件,而雙擊過程當中就不適合觸發 click 事件了。由此能夠看出 click 事件觸發表明一輪觸摸事件的結束。app

既然說tap事件是模擬出來的,咱們能夠看下 Zepto 對 singleTap 事件的處理。見 源碼 136-143 行,能夠看出在 touchend響應 250ms 無操做後,則觸發 singleTap

參考

博文

書籍

  • 《移動 Web 手冊》
以上部分資料蒐集整理自網絡,若有不對的地方但願及時告知,歡迎你們批評指正,謝謝!
相關文章
相關標籤/搜索