最近在使用
zepto.js
的時候,發現其
tap
事件的一個BUG,被産品和測試同學反複找了幾次之後,終于下定決定去研究
zepto
的源碼,并解決了問題。
BUG情況說明:
給頁面
<a>
标簽綁定了
tap
事件,在移動裝置上點選按鈕貌似一切正常,可以正常響應。
但是,把頁面上下滑動幾次之後,或者在滑動時手指滑動出移動螢幕之外,之後再點選按鈕,就會發現第一次點選的時候事件沒被觸發,需要點選第二次才會正常,而且幾乎是必現的。一開始的時候我還以為是安卓Webview要擷取頁面焦點的原因,後來研究了下
zepto
源碼之後,發現原來不是。
Tap事件實作原理:
其實不用看代碼都猜的出來,是用
touchstart
touchmove
touchend
這三個事件去實作的,沒錯,就是這樣。
但是為了區分“點選”和“拖動”兩個動作,
zepto
是用了
deltaX
和
deltaY
兩個變量去分别記錄手指在觸碰到螢幕時到離開螢幕時的x軸和y軸距離,如果
deltaX>30px
或者
deltaY>30px
,則認為是“拖動”動作,就不會觸發
tap
事件了。
一切看似正常,但是細看一下,原來
deltaX
和
deltaY
的置0的是在
touchend
裡實作的,而移動裝置上,有兩種情況是有可能導緻
touchend
事件沒觸發(1.快速劃動螢幕多次,2.劃動螢幕時手指劃出螢幕邊界),這樣
deltaX
和
deltaY
就不會被置0了,等到下次再點選的時候,
deltaX
和
deltaY
就有可能大于
30px
,導緻
tap
事件不被觸發。
問題解決:
想必大家都知道該怎麼解決,沒錯,就是在
touchstart
時添加
deltaX
和
deltaY
的置0,代碼如下:
.on('touchstart MSPointerDown pointerdown', function(e){
deltaX = deltaY = ;
......
修改位置:zepto裡或者touch.js裡修改。