註明:自己學習javascript時間不長,最近一直在做web端的手機網頁和微信應用,由於最近有用到類似fastclick的功能,在原來的程序中用touchstart和touchend事件模擬,現在嘗試將其封裝,得到了以下兩種有問題的方案。分享給大家,另求大神指導
在手機端Web app開發中,click事件的300ms的延遲,會造成反應緩慢,尤其在低階機中尤為明顯。而使用touchstart或touchend事件,會和預設的滾輪事件發生衝突,這也不是我們所期望的。
所以,自己動手,豐衣足食,寫了一個快速點擊事件的原生js代碼(考慮到web app開發的環境,我們暫時無需考慮對IE等瀏覽器的兼容)。
實作方法1如下:
function FastClickEvent(handler){ var fastclick = { handler : handler, bind : function(query){ var targetList = document.querySelectorAll(query); for(var i=0,len=targetList.length;i<len;i++) { targetList[i].addEventListener('touchstart',handleEvent); targetList[i].addEventListener('touchend',handleEvent); } }, unbind : function(query){ var targetList = document.querySelectorAll(query); for(var i=0,len=targetList.length;i<len;i++) { targetList[i].removeEventListener('touchstart',handleEvent); targetList[i].removeEventListener('touchend',handleEvent); } } } var touchX = 0 ,touchY = 0; function handleEvent(event){ switch(event.type) { case 'touchstart': touchX = event.touches[0].clientX; touchY = event.touches[0].clientY; break; case 'touchend': var x = event.changedTouches[0].clientX; var y = event.changedTouches[0].clientY; if(Math.abs(touchX-x)<5||Math.abs(touchY-y)<5) fastclick.handler(event); break; } }; return fastclick; };
原理:根據連續touchstart和touchend事件發生時位置的變化,來判斷是否是一次點擊
調用事件:用一個handler函數來註冊事件。然後將註冊好的FastClickEvent事件,透過bind方法,綁定到對應的元素上去。如下:
var handler = function(event){ console.log(event.target.id+" fastclicked"); } var fastClick = new FastClickEvent(handler); fastClick.bind("div");
這段程式碼,我們為所有的div元素註冊了fastclick的handler事件。呼叫fastClick.unbind來解除元素的綁定。
但是這段程式碼有一個問題,為了讓handleEvent事件能夠存取touchX,touchY。我採用了閉包的手法,這意味著每次new一個FastClickEvent事件對象,都要在記憶體中再次注入重複的handleEvent函數。至於重複的touchX,touchY,更是不必多說了。
新手求助:原本是想把handleEvent函數寫到原型裡,但是產生的一個問題是handleEvent(event)的this對像是windows,也就是說,我取不到touchX和touchY以及handler對象,造成訪問錯誤。
有比較簡單的解決思路,就是只註冊一個fastClickEvent事件,然後在處理程序中根據event.target的實際值(即發生事件的物件上)來決定回應的內容。
但是,這意味著你必須對所有的fastclick事件都非常熟悉。
用這種方法帶來的好處在於,由於你只有一個handleEvent函數,所以基本上來說,在頁面釋放之前,除非是你不想再觸發fastclick事件,否則無需去解綁任何元素的fastclick事件(即使你解綁了,記憶體中仍然存在該handler函數)。而且,你可以很方便的用bind(query)來加入任何動態產生的元素的fastclick事件,只要你在handler函數中已經寫好對應的處理程序。
如果你想新增多個fastclick事件,而且可能要在多個地方註冊,那麼也只要new一個新的FastClickEvent對象,然後綁定到對應的元素中去就可以了。
下面,介紹一種使用EventTarget類別的方法。首先來看看EventTarget
function EventTarget(){ this.handlers = {}; } EventTarget.prototype = { constructor: EventTarget, addHandler : function(type,handler){ if(typeof this.handlers[type] == "undefined"){ this.handlers[type]=[]; } this.handlers[type].push(handler); }, fire : function(event){ if(!event.target){ event.target = this; } if(this.handlers[event.type] instanceof Array){ var handlers = this.handlers[event.type]; for(var i=0,len=handlers.length;i<len;i++){ handlers[i](event); } } }, removeHandler : function(type,handler){ if(this.handlers[type] instanceof Array){ var handlers = this.handlers[type]; for(var i=0,len=handler.length;i<len;i++){ if(handlers[i]==handler){ break; } } handlers.splice(i,1); } } }
這個類,是一個用來新增、移除、實作自訂類別的介面。參考《JavaScript高階程式設計第三版》P616-617
那麼,如何把這個類,變成我們的fastclick事件介面呢?
定義一個全域變量,用這個變數來完成所有的fastclick事件註冊、刪除以及新增
var FastClick = function(){ var fastclick = new EventTarget(), touchX = 0 , touchY = 0; function handleEvent(event){ switch(event.type) { case 'touchstart': touchX = event.touches[0].clientX; touchY = event.touches[0].clientY; break; case 'touchend': var x = event.changedTouches[0].clientX; var y = event.changedTouches[0].clientY; if(Math.abs(touchX-x)<5||Math.abs(touchY-y)<5) fastclick.fire({type:'fastclick',target:event.target}); break; } }; fastclick.bind = function(query) { var targetList = document.querySelectorAll(query); for(var i=0,len=targetList.length;i<len;i++) { targetList[i].addEventListener('touchstart',handleEvent); targetList[i].addEventListener('touchend',handleEvent); } } Fastclick.unbind = function(query){ var targetList = document.querySelectorAll(query); for(var i=0,len=targetList.length;i<len;i++) { targetList[i].removeEventListener('touchstart',handleEvent); targetList[i].removeEventListener('touchend',handleEvent); } } return fastclick; }();
這個全域變數FastClick可以用來加入任意的fastclick事件。
下面來講講如何呼叫。
新增事件函數:
FastClick.addHandler('fastclick',function(event){});
刪除事件函數://匿名事件無法刪除
FastClick.removeHandler('fastclickHandler('fastclick);
綁定元素FastClick.bind("div");解綁FastClick.unbind("div");用這個方法,同樣需要我們在handtarler事件中對event. ,因為雖然這個方法可以加入多個fastclick事件,但是,事件在執行的過程中是按順序一個一個執行的,也就是說,可能會執行你並不想執行的函數。 帶來的好處在於,可以註冊多個fastclick事件,而且無需再次綁定,就可以執行了。比如說,
FastClick.bind("div"); FastClick.addHandler(handler1); FastClick.addHandler(handler2);那麼,當快速點擊事件發生在任一div元素時,就會順序執行handler1和handler2。 如果我們呼叫removeHandler來刪除handler1或handler2,那麼對應的函數就不會再執行了。 另外,要注意的是,在handler函數中,this物件是FastClick.handlers['fastclick']這個數組,一般情況下,我們用event.target來取得發生事件的物件。 用這種方法,基本上克服了上面方法的問題,而且,對這個對象重複new並沒有多大的意義,除非你不想對event.target做預判,從而生成一大堆的FaskClick類,但這顯然是不高效的。 新手求助:如何能夠實現特定的元素的綁定執行的函數,也就是: 能夠呼叫FastClick.bind(query,handler);實現對符合query條件的元素添加handler的fastclick事件。

在本週的綜述中:Firefox獲得了類似鎖匠的力量,三星的Galaxy Store開始支持Progressive Web Apps,CSS Subgrid正在Firefox發貨

在本週的綜述中:Internet Explorer進入Edge,Google搜索控制台吹捧新的速度報告,而Firefox給出了Facebook&#039; s Notification

蓋茨比(Gatsby)進行了出色的處理和處理圖像。例如,它可以幫助您節省圖像優化的時間,因為您不必手動


熱AI工具

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

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

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

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

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

WebStorm Mac版
好用的JavaScript開發工具

mPDF
mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),

DVWA
Damn Vulnerable Web App (DVWA) 是一個PHP/MySQL的Web應用程序,非常容易受到攻擊。它的主要目標是成為安全專業人員在合法環境中測試自己的技能和工具的輔助工具,幫助Web開發人員更好地理解保護網路應用程式的過程,並幫助教師/學生在課堂環境中教授/學習Web應用程式安全性。 DVWA的目標是透過簡單直接的介面練習一些最常見的Web漏洞,難度各不相同。請注意,該軟體中