摘要:所以這種情況下是不符合點擊事件的定義的。,關于移動端的點擊事件總結完了,可能你都沒想到一個簡單的點擊事件會有那么多坑,如果你在工作中可能會涉及到移動端開發的話,相信這篇文章還是值得你點贊和收藏的,畢竟是踩了那么多坑的經驗總結。
看標題的時候你可能會想,點擊事件有什么好說的,還寫一篇攻略?哈哈,如果你這么想,只能說明你too young to simple.
接觸過移動端開發的同學可能都會面臨點擊事件的第一個問題:click事件的300ms延遲響應。不能立即響應給體驗造成了很大的困擾,因此解決這個問題就成為了必然。
這個問題的解決方案就是:zepto.js的tap事件。tap事件可以理解為在移動端的click事件,而zepto.js因為幾乎完全復制jQuery的api,因此常常被用在h5的開發上用來取代jquery.
由于模塊化的原因,導致有的同學下載的zepto.js的模塊并不全,造成了一大堆悲劇,以為zepto.js不支持一些方法,所以,下載的時候注意一點。
然而事情到這里并沒有結束,因為tap事件解決了一個300ms延遲問題,卻帶來了一個新的重大bug,點擊穿透。
點擊穿透的意思,就是如果一個絕對定位或者固定定位元素處于頁面最頂層,對這個元素綁定一個點擊事件,那么你點擊這個點對應的下面凡是有點擊事件或者a標簽都會被觸發執行。這里就不貼圖了,自行腦補各種彈窗,這種情況還是非常多的。
為了解決這個問題,有的人試圖用touchend來搞定。touchend會在手指離開手機屏幕時觸發一次。沒有300ms延遲,沒有點擊穿透,看上去簡直就是完美的解決方案。可是!
先在這里簡單總結一個小知識點。
移動端有touchstart, touchmove, touchend, 以及tap
pc端有mousedown, mousemove, mouseup, click。
他們的關系和作用幾乎可以對應起來,分別表示按下,滑動,松開。pc端可以用前面三個事件實現拖拽,移動端也可以用前面三個事件實現的滑動。
所以,在pc端不用mouseup來替換click,就是因為他在松開鼠標的時候就會觸發,導致如果我在很遠的區域滑動到目標元素,然后松開,這樣的情況也會觸發mouseup與touchend事件。所以這種情況下是不符合點擊事件的定義的。而且如果你在某種情況下,對某一個事件需要同時綁定拖拽和點擊,就更加沒辦法解決了。
另外還有一個很重要的原因導致touchend不能用來替換點擊,是因為PC端不支持。老板們常常希望自己的頁面不僅僅能夠在移動端展示,因此還得想其他辦法。
我知道有經驗的同學讀這篇文章的時候,早就在想fastclick.js了。是的,目前來看,這是一個非常好的解決方案。為了解決300ms延遲的問題,zepto.js給出了tap事件替換的方案,而fastclick.js則是在想辦法讓click事件的延遲消除。因此任然是使用click事件,也就不會有點擊穿透的問題。
首先想辦法引入fastclick.js
如果你使用原生js開發則進行如下聲明即可。
if ("addEventListener" in document) { document.addEventListener("DOMContentLoaded", function() { FastClick.attach(document.body); }, false); }
如果你想使用jquery
$(function() { FastClick.attach(document.body); });
如果你在使用CommonJS風格的框架,比如requirejs
var attachFastClick = require("fastclick"); attachFastClick(document.body);
AMD
var FastClick = require("fastclick"); FastClick.attach(document.body, options);
進行對應的聲明之后,你就可以在移動端頁面中放心大膽的使用click事件了。說到這里,就會有一個關于zepto.js與jquery選擇的問題。說起來又可以寫一大篇文章了,簡單來說就是,實際開發中你就會發現zepto還是有點不太爽,雖然體積小點,既然click延遲的問題已經解決了,我還是更偏向于使用jquery.
當然,我們要踩的坑并沒有結束 - -!
最近開發了一個小頁面,財經日歷,在日歷部分,我需要同時給代表每一天的元素事件實現獲取當天資訊的需求,又要給整個日歷部分實現能夠左右滑動來選取上一月和下一月的功能。所以我需要同時對日歷部分綁定click事件和實現滑動的touchstart,touchmove,touchend事件。
這個時候問題出現了。在安卓手機上,對同一個元素,如果我綁定了click事件,然后在綁定touchstart事件,click事件會處于幾乎失效的狀態。就算用了fastclick事件也無法避免這個問題
錯誤演示大概如下
$area.on("click", ".weeknumber", function() { // 點擊每一天獲取當天資訊 }) // 實現左右滑動 $area.on("touchstart", function() {}) .on("touchmove", function() {}) .on("touchend", function() {})
動手能力強的同學可以去試試這個坑,這種情況下,fastfclick肯定是沒辦法解決的。怎么辦?
我的第一次嘗試,是在當滑動距離為0的時候,運行點擊事件里面的內容。我們知道在實現滑動[不知道如何實現的同學,是時候關注我的公眾號了,搜索isreact找到我]的時候,會計算一個滑動距離。
// 實現滑動的大概代碼 // 滑動元素translateX的初始值 var iscroll = device_width, // 用來計算的中間值 istarX = 0, // 手指第一次點在屏幕上的x坐標 istart_pageX = 0; // 綁定事件 $area.on("touchstart", touchstart) .on("touchmove", touchmove) .on("touchend", touchend); function touchstart(event) { event.preventDefault(); istartX = iscroll; istart_pageX = event.originalEvent.changedTouches[0].pageX; } function touchmove(event) { // 滑動過程中手指位置x坐標會不停變動,這里會保存一個當前位置與初始位置的一個差值 var distance = event.originalEvent.changedTouches[0].pageX - istart_pageX; iscroll = istartX + distance; // 這里是我自定義的一個css方法,用來設置元素translateX的當前值 Utils.css(area, { translateX: iscroll }); } function touchend(event) { var distance = event.originalEvent.changedTouches[0].pageX - istart_pageX; $area.off("touchstart touchmove touchend"); // 根據差值的不同,執行不同的動作 if (distance < -80) { slideNext(function() { addEventSlider($area); }) } else if (distance > 80) { slidePrev(function() { addEventSlider($area); }) } else if (distance == 0) { /* 當差值為0時,我認為這是執行了一次點擊 */ addEventSlider($area); } else { ani(area).animate(400, "easeout", { x: -device_width }, function() { iscroll = -device_width; addEventSlider($area); }) } }
上面就是我的滑動功能的實現,中間會有一些自定義的方法,因此沒辦法你們直接就復制過去運行。但是原理已經講得還算明白,可以自己嘗試一些簡單的實現。關注我公眾號會有更加詳細的講解哦!
我的這一次嘗試,就是在滑動差值distance為0的時候,認為這是一次點擊,因此執行點擊事件應該有的動作。本來我以為這就能夠解決了,測試的時候也通過了。但是 - -!產品同學非常有執念的在日歷上點擊了50多下,結果發現,多次點擊之后,在點就失去效果了!!!
當發現這個bug的時候,我的內心是崩潰的。好吧,只能說,試圖用touchend來代替點擊事件的想法終究還是有一點不成熟。硬著頭皮想辦法繼續解決上面的問題。再三思考各種解決方案,最終決定自己封裝一個tap事件。封裝的tap事件的代碼如下。
http://yangbo5207.github.io/s...
這是對jquery事件的一個拓展,讓jquery也能夠使用tap事件。放在jquery后面引入就能夠立即使用了。除此之外還擴展了longTap,swipe兩個事件。
使用方式和其他一樣。
$area.on("tap", function() {}); $area.tap(function() {})
當然我封裝的這個tap,任然有避免不了的點擊穿透bug,所以,最終的解決方案是:對于需要同時綁定點擊事件和滑動事件的元素,用tap事件,其他情況都用click事件即可。需要結合我的tap.js與fastclick.js來完美解決這個問題。心累啊,終于是搞定了。
OK,關于移動端的點擊事件總結完了,可能你都沒想到一個簡單的點擊事件會有那么多坑,如果你在工作中可能會涉及到移動端開發的話,相信這篇文章還是值得你點贊和收藏的,畢竟是踩了那么多坑的經驗總結。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/49893.html
摘要:所以這種情況下是不符合點擊事件的定義的。,關于移動端的點擊事件總結完了,可能你都沒想到一個簡單的點擊事件會有那么多坑,如果你在工作中可能會涉及到移動端開發的話,相信這篇文章還是值得你點贊和收藏的,畢竟是踩了那么多坑的經驗總結。 看標題的時候你可能會想,點擊事件有什么好說的,還寫一篇攻略?哈哈,如果你這么想,只能說明你too young to simple. 接觸過移動端開發的同學可能都...
摘要:所以這種情況下是不符合點擊事件的定義的。,關于移動端的點擊事件總結完了,可能你都沒想到一個簡單的點擊事件會有那么多坑,如果你在工作中可能會涉及到移動端開發的話,相信這篇文章還是值得你點贊和收藏的,畢竟是踩了那么多坑的經驗總結。 看標題的時候你可能會想,點擊事件有什么好說的,還寫一篇攻略?哈哈,如果你這么想,只能說明你too young to simple. 接觸過移動端開發的同學可能都...
摘要:像素像素是一個相對單位。相對不同屏幕,其實際像素大小不同。解決方案直接使用實現的終端適配有興趣的小伙伴可以看下的解決方案使用實現手淘頁面的終端適配地址移動端適配單位的坑你知道多少關于移動端布局的一些總結 網頁尺寸單位 百分比(%) 英寸(in) 厘米(cm) 毫米(mm) 磅數(pt) 12 點活字(pc) 字母高度一半(ex) 父級字體(em) 像素(px) 根元素字體(rem) ...
摘要:為此決定自研一個富文本編輯器。例如當要轉化的對象有環存在時子節點屬性賦值了父節點的引用,為了關于函數式編程的思考作者李英杰,美團金融前端團隊成員。只有正確使用作用域,才能使用優秀的設計模式,幫助你規避副作用。 JavaScript 專題之惰性函數 JavaScript 專題系列第十五篇,講解惰性函數 需求 我們現在需要寫一個 foo 函數,這個函數返回首次調用時的 Date 對象,注意...
閱讀 1174·2021-09-27 13:34
閱讀 981·2021-09-13 10:25
閱讀 511·2019-08-30 15:52
閱讀 3450·2019-08-30 13:48
閱讀 648·2019-08-30 11:07
閱讀 2167·2019-08-29 16:23
閱讀 1993·2019-08-29 13:51
閱讀 2328·2019-08-26 17:42