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

描述

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

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

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

效果以下:
效果圖git

緣由

什麼是點擊穿透?

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

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

解決方案

1. 改用 touch 事件

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

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

2. 使用 fastclick 插件

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

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

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

其餘

tap 一詞

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

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

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

參考

博文

書籍

  • 《移動 Web 手冊》

相關文章
相關標籤/搜索