這次帶給大家如何使用Zepto tap事件的穿透與點透(附程式碼),使用Zepto tap事件的穿透與點透注意事項有哪些,下面就是實戰案例,一起來看一下。
首先,什麼是zepto tap事件穿透?
tap事件穿透就是,有多個層級上有綁定事件,最上層的綁定了tap事件,下層綁定了click事件,在執行完上層事件後會觸發下層事件,進而出現事件穿透。如果下層是input標籤,必穿透。
究其原因:
是因為zepto實作tap事件是冒泡到document上時才觸發的,也就是tap事件是綁定在document上,而click事件有延遲執行。
下面我們貼下zepto.1.1.6 tap事件的原始碼:
<span style="font-size: 14px;">;(function($){<br> var touch = {},<br> touchTimeout, tapTimeout, swipeTimeout, longTapTimeout,<br> longTapDelay = 750,<br> gesture<br> function swipeDirection(x1, x2, y1, y2) {<br> return Math.abs(x1 - x2) >=<br> Math.abs(y1 - y2) ? (x1 - x2 > 0 ? 'Left' : 'Right') : (y1 - y2 > 0 ? 'Up' : 'Down')<br> }<br> function longTap() {<br> longTapTimeout = null<br> if (touch.last) {<br> touch.el.trigger('longTap')<br> touch = {}<br> }<br> }<br> function cancelLongTap() {<br> if (longTapTimeout) clearTimeout(longTapTimeout)<br> longTapTimeout = null<br> }<br> function cancelAll() {<br> if (touchTimeout) clearTimeout(touchTimeout)<br> if (tapTimeout) clearTimeout(tapTimeout)<br> if (swipeTimeout) clearTimeout(swipeTimeout)<br> if (longTapTimeout) clearTimeout(longTapTimeout)<br> touchTimeout = tapTimeout = swipeTimeout = longTapTimeout = null<br> touch = {}<br> }<br> function isPrimaryTouch(event){<br> return (event.pointerType == 'touch' ||<br> event.pointerType == event.MSPOINTER_TYPE_TOUCH)<br> && event.isPrimary<br> }<br> function isPointerEventType(e, type){<br> return (e.type == 'pointer'+type ||<br> e.type.toLowerCase() == 'mspointer'+type)<br> }<br> $(document).ready(function(){<br> var now, delta, deltaX = 0, deltaY = 0, firstTouch, _isPointerType<br> if ('MSGesture' in window) {<br> gesture = new MSGesture()<br> gesture.target = document.body<br> }<br> $(document)<br> .bind('MSGestureEnd', function(e){<br> var swipeDirectionFromVelocity =<br> e.velocityX > 1 ? 'Right' : e.velocityX 1 ? 'Down' : e.velocityY if (swipeDirectionFromVelocity) {<br> touch.el.trigger('swipe')<br> touch.el.trigger('swipe'+ swipeDirectionFromVelocity)<br> }<br> })<br> .on('touchstart MSPointerDown pointerdown', function(e){<br> if((_isPointerType = isPointerEventType(e, 'down')) &&<br> !isPrimaryTouch(e)) return<br> firstTouch = _isPointerType ? e : e.touches[0]<br> if (e.touches && e.touches.length === 1 && touch.x2) {<br> // Clear out touch movement data if we have it sticking around<br> // This can occur if touchcancel doesn't fire due to preventDefault, etc.<br> touch.x2 = undefined<br> touch.y2 = undefined<br> }<br> now = Date.now()<br> delta = now - (touch.last || now)<br> touch.el = $('tagName' in firstTouch.target ?<br> firstTouch.target : firstTouch.target.parentNode)<br> touchTimeout && clearTimeout(touchTimeout)<br> touch.x1 = firstTouch.pageX<br> touch.y1 = firstTouch.pageY<br> if (delta > 0 && delta touch.last = now<br> longTapTimeout = setTimeout(longTap, longTapDelay)<br> // adds the current touch contact for IE gesture recognition<br> if (gesture && _isPointerType) gesture.addPointer(e.pointerId);<br> })<br> .on('touchmove MSPointerMove pointermove', function(e){<br> if((_isPointerType = isPointerEventType(e, 'move')) &&<br> !isPrimaryTouch(e)) return<br> firstTouch = _isPointerType ? e : e.touches[0]<br> cancelLongTap()<br> touch.x2 = firstTouch.pageX<br> touch.y2 = firstTouch.pageY<br> deltaX += Math.abs(touch.x1 - touch.x2)<br> deltaY += Math.abs(touch.y1 - touch.y2)<br> })<br> .on('touchend MSPointerUp pointerup', function(e){<br> if((_isPointerType = isPointerEventType(e, 'up')) &&<br> !isPrimaryTouch(e)) return<br> cancelLongTap()<br> // swipe<br> if ((touch.x2 && Math.abs(touch.x1 - touch.x2) > 30) ||<br> (touch.y2 && Math.abs(touch.y1 - touch.y2) > 30))<br> swipeTimeout = setTimeout(function() {<br> touch.el.trigger('swipe')<br> touch.el.trigger('swipe' + (swipeDirection(touch.x1, touch.x2, touch.y1, touch.y2)))<br> touch = {}<br> }, 0)<br> // normal tap<br> else if ('last' in touch)<br> // don't fire tap when delta position changed by more than 30 pixels,<br> // for instance when moving to a point and back to origin<br> if (deltaX // delay by one tick so we can cancel the 'tap' event if 'scroll' fires<br> // ('tap' fires before 'scroll')<br> tapTimeout = setTimeout(function() {<br> // trigger universal 'tap' with the option to cancelTouch()<br> // (cancelTouch cancels processing of single vs double taps for faster 'tap' response)<br> var event = $.Event('tap')<br> event.cancelTouch = cancelAll<br> touch.el.trigger(event)<br> // trigger double tap immediately<br> if (touch.isDoubleTap) {<br> if (touch.el) touch.el.trigger('doubleTap')<br> touch = {}<br> }<br> // trigger single tap after 250ms of inactivity<br> else {<br> touchTimeout = setTimeout(function(){<br> touchTimeout = null<br> if (touch.el) touch.el.trigger('singleTap')<br> touch = {}<br> }, 250)<br> }<br> }, 0)<br> } else {<br> touch = {}<br> }<br> deltaX = deltaY = 0<br> })<br> // when the browser window loses focus,<br> // for example when a modal dialog is shown,<br> // cancel all ongoing events<br> .on('touchcancel MSPointerCancel pointercancel', cancelAll)<br> // scrolling the window indicates intention of the user<br> // to scroll, not tap or swipe, so cancel all ongoing events<br> $(window).on('scroll', cancelAll)<br> })<br> ;['swipe', 'swipeLeft', 'swipeRight', 'swipeUp', 'swipeDown',<br> 'doubleTap', 'tap', 'singleTap', 'longTap'].forEach(function(eventName){<br> $.fn[eventName] = function(callback){ return this.on(eventName, callback) }<br> })<br>})(Zepto)</span>
詳細分析:
#根據zepto原始碼,我們很清楚地知道tap事件是透過綁定在document上的touch事件來模擬的。所以使用者在點擊tap事件(touchstart、touchend)時需要冒泡到document上才會觸發。然而使用者在touchstart和touchend時會觸發click事件,但此時click事件處於延遲300ms,如果在這300ms之內tap事件已經完成,將上層元素刪除或隱藏。在300ms到來之際,根據click事件的原則(當click事件的元素處於最上層時會處於click事件,所以有的時候錯誤的z-index的設定導致無法觸發click事件),下層事件被執行,出現穿透現象。讓下層是input元素,即使沒有綁定click事件,由於其預設聚焦彈出鍵盤,穿透現象尤其嚴重。
解決方案:
1、github上有個fastclick插件,用來規避click事件的延時執行。引入文件後添加如下程式碼,並用click取代可能會導致穿透的tap事件元素。
$(function(){ new FastClick(document.body); })
2、監聽touchend事件來取代tap,或touchstart,並阻止冒泡
$("#close").on("touchend",function(e){ $("#alertBox").hide(); e.preventDefault(); });
3、使用css3的pointer-events : true 和 pointer-events : none交替使用對下層元素設置,阻止觸發click事件。
4、延時消失上層元素,使得無法觸發下層click事件,盡量在延時350ms以上(本人在ios9.2上微信6.3.15上測試過)。不過這樣稍微有些體驗不好,我們可以使用css3過度來改善體驗。
setTimeout(function(){ $(#alertBox).hide(); } , 350 );
5、終極方案:用click取代所有tap。由於click的延時,導致體驗問題,最好加上fastclick插件。
以下是我寫了一個簡單的範例:可以用手機存取http://property.pingan.com/app/test/jltest/tap-through.html?a= 1
透過例子,我們可以很明顯的看到事件穿透後底層的button有按下的效果。在頻繁的測試過程中,由於微信會快取頁面導致無法看到即時修改的內容,我們可以透過為url增加一些沒用的參數如a=1,這樣瀏覽器就會重新載入。
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=0"> <title>test-tap-through</title> <script src="js/zepto.min.js" charset="utf-8"></script> <style media="screen"> body{ margin: 0; padding: 0; } .test1,.test2{ position: relative; } .button{ width: 90%; height: 75px; background-color: #00ffff; margin: 5%; line-height: 75px; text-align: center; font-size: 40px; } .box{ position: absolute; top:0; left: 0; width: 50%; height: 200px; background-color: #ff00ff; margin: 5%; line-height: 100px; text-align: center; font-size: 40px; z-index: 100; } </style> </head> <body> <p> <input type="button" id="button1" value="button1"> <input type="button" id="button2" value="button2"> <p id="box1" style="display:none">box1</p> <p id="box2" style="display:none">box2</p> </p> <p> <input type="button" id="button3" value="button3"> <input type="button" id="button4" value="button4"> <p id="box3" style="display:none">box3</p> <p id="box4" style="display:none">box4</p> </p> </body> <script type="text/javascript"> $("#button1").click(function(){ $("#box2").hide(); $("#box1").show(); }); $("#button2").click(function(){ $("#box1").hide(); $("#box2").show(); }); $("#box2").tap(function(){ $("#box2").hide(); }); $("#box1").tap(function(){ $("#box1").hide(); }); $("#button3").click(function(){ $("#box4").hide(); $("#box3").show(); }); $("#button4").click(function(){ $("#box3").hide(); $("#box4").show(); }); $("#box3").tap(function(){ setTimeout(function(){$("#box3").hide();},350); }); $("#box4").tap(function(){ setTimeout(function(){$("#box4").hide();},350); }); </script> </html>
相信看了本文案例你已經掌握了方法,更多精彩請關注php中文網其它相關文章!
推薦閱讀:
以上是如何使用Zepto tap事件的穿透與點透(附程式碼)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

是的,JavaScript的引擎核心是用C語言編寫的。 1)C語言提供了高效性能和底層控制,適合JavaScript引擎的開發。 2)以V8引擎為例,其核心用C 編寫,結合了C的效率和麵向對象特性。 3)JavaScript引擎的工作原理包括解析、編譯和執行,C語言在這些過程中發揮關鍵作用。

JavaScript是現代網站的核心,因為它增強了網頁的交互性和動態性。 1)它允許在不刷新頁面的情況下改變內容,2)通過DOMAPI操作網頁,3)支持複雜的交互效果如動畫和拖放,4)優化性能和最佳實踐提高用戶體驗。

C 和JavaScript通過WebAssembly實現互操作性。 1)C 代碼編譯成WebAssembly模塊,引入到JavaScript環境中,增強計算能力。 2)在遊戲開發中,C 處理物理引擎和圖形渲染,JavaScript負責遊戲邏輯和用戶界面。

JavaScript在網站、移動應用、桌面應用和服務器端編程中均有廣泛應用。 1)在網站開發中,JavaScript與HTML、CSS一起操作DOM,實現動態效果,並支持如jQuery、React等框架。 2)通過ReactNative和Ionic,JavaScript用於開發跨平台移動應用。 3)Electron框架使JavaScript能構建桌面應用。 4)Node.js讓JavaScript在服務器端運行,支持高並發請求。

Python更適合數據科學和自動化,JavaScript更適合前端和全棧開發。 1.Python在數據科學和機器學習中表現出色,使用NumPy、Pandas等庫進行數據處理和建模。 2.Python在自動化和腳本編寫方面簡潔高效。 3.JavaScript在前端開發中不可或缺,用於構建動態網頁和單頁面應用。 4.JavaScript通過Node.js在後端開發中發揮作用,支持全棧開發。

C和C 在JavaScript引擎中扮演了至关重要的角色,主要用于实现解释器和JIT编译器。1)C 用于解析JavaScript源码并生成抽象语法树。2)C 负责生成和执行字节码。3)C 实现JIT编译器,在运行时优化和编译热点代码,显著提高JavaScript的执行效率。

JavaScript在現實世界中的應用包括前端和後端開發。 1)通過構建TODO列表應用展示前端應用,涉及DOM操作和事件處理。 2)通過Node.js和Express構建RESTfulAPI展示後端應用。

JavaScript在Web開發中的主要用途包括客戶端交互、表單驗證和異步通信。 1)通過DOM操作實現動態內容更新和用戶交互;2)在用戶提交數據前進行客戶端驗證,提高用戶體驗;3)通過AJAX技術實現與服務器的無刷新通信。


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

Dreamweaver Mac版
視覺化網頁開發工具

VSCode Windows 64位元 下載
微軟推出的免費、功能強大的一款IDE編輯器

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

Safe Exam Browser
Safe Exam Browser是一個安全的瀏覽器環境,安全地進行線上考試。該軟體將任何電腦變成一個安全的工作站。它控制對任何實用工具的訪問,並防止學生使用未經授權的資源。

Dreamweaver CS6
視覺化網頁開發工具