摘要:瀏覽器自動響應后續處理。瀏覽器行為部分是猜測,未驗證。至于解決方案網上有很多,目前最好的是,不過也會有其他問題,例如在滑動中點擊之類的。
問題來源
年前去阿里面試,過程中說道了fastclick解決iPhone機器上300ms點擊延遲的問題,然后就被問到了zepto的“點擊穿透”的現象以及產生這個具體原因,當時回答的不是很好,主要是沒有特別深入的去研究這個原因,只是知道有這個現象和問題,大概怎么解決,面試完了之后有一天突然想起來了,就決定仔細的研究下。
其實有好多文章都寫了,內容有很多我就不重復,總結以下幾點:
300ms延遲是由于瀏覽器要判斷是單機還是雙擊造成的延遲處理點擊事件
fastclick解決方式用touchstart結合touchmove以及touchend替代click事件
zepto的tap會“擊穿”頁面是由于既響應了自身的tap(也就是touch事件),又沒有攔截掉原來的click事件,導致重復執行了2次事件,在有遮罩彈層的時候就會出現“擊穿”效果。如果不太明白的話看這篇文章zepto的擊穿
年前探究當時研究到這里時候我有一個大大的疑問就是為什么click延遲執行之后,遮罩層下面的頁面的click事件會被觸發,我明明點擊的遮罩層的A按鈕,為何下面頁面的B按鈕的事件會執行。按照我最初的想法,應該是繼續執行A按鈕的事件啊!!!此時我內心是這樣的
于是我開始探究這個問題,我搜了下大概的資料,基本都沒有講這個具體原因的,也許是我打開方式不對,反正沒有找到,無奈之下,我只能翻看fastclick的源碼來看它為何沒有出現這個問題,然后看到了sendClick的代碼,心里猛然有了一個猜想。
FastClick.prototype.sendClick = function(targetElement, event) { var clickEvent, touch; // On some Android devices activeElement needs to be blurred otherwise the synthetic click will have no effect (#24) if (document.activeElement && document.activeElement !== targetElement) { document.activeElement.blur(); } touch = event.changedTouches[0]; // Synthesise a click event, with an extra attribute so it can be tracked clickEvent = document.createEvent("MouseEvents"); clickEvent.initMouseEvent(this.determineEventType(targetElement), true, true, window, 1, touch.screenX, touch.screenY, touch.clientX, touch.clientY, false, false, false, false, 0, null); clickEvent.forwardedTouchEvent = true; targetElement.dispatchEvent(clickEvent); };
注意這里的initMouseEvent,當時就在想肯定和mouseEvent執行的原理有關了,到這個階段算是有了眉目。
接著搞緊接著,開始過年,過年期間享受了生活,并沒有碰代碼和文檔(好墮落的感覺......),加上我跳槽的空檔和折騰,年后稍稍穩定下來了,最近又想起了年前這探究一半的猜想,開始繼續搞了起來,順便收收心,好進入狀態。
先說猜想--click事件最開始其實在瀏覽器當中被捕捉的時候,只有mouseEvent的相關屬性,也就是我們平常在console.log(event)的一部分,之后,瀏覽器才會結合html,js產生我們常說的click時間,接著觸發我們使用js綁定的函數。
基于這個猜想,我開始翻閱mozilla和W3C的文檔來了解mouseEvent。
翻看文檔之后發現mouseEvent果然只有 screenX,screenY,clientX,clientY,ctrlKey,altKey,shiftKey,metaKey,button,buttons,EventTarget?relatedTarget。
其中button和buttons指的是鼠標的按鈕類型,就是左鍵,右鍵,滾輪這些。用數字代替,0表示左鍵,1是滾輪,2是右鍵,其他更多功能鍵,都是大于2的。
從上面我們能看出來,其實對于mouseEvent而言,它只知道我們在屏幕的哪個位置,做了什么動作(鼠標操作),并不知道是在哪個element上面。這也就是fastclick還原用戶點擊事件最后做的事情。
clickEvent.initMouseEvent(this.determineEventType(targetElement), true, true, window, 1, touch.screenX, touch.screenY, touch.clientX, touch.clientY, false, false, false, false, 0, null); // detremineEvenType是fastclick封裝返回mouseEvent的type類型,就是click還是mouseDown
初始化一個鼠標事件,然后dispatch這個鼠標事件。瀏覽器自動響應后續處理。
接著來看click的定義,如下圖所示:
click會多了Event.target,而且必須是一個?topmost event target,在mozilla定義有些不太相同,多了currentTarget和type等。
先來看EventTarget的定義:EventTarget is an interface implemented by objects that can receive events and may have listeners for them.
Element, document, and window are the most common event targets, but other objects can be event targets too, for example?XMLHttpRequest, AudioNode,AudioContext, and others.
從定義就能看出來了,如果是click事件必須要有一個target來承載這次鼠標事件。一般來說target要么是element要么是document,如果都沒有那么就是window對象了。到這里大家應該就比較明白,這里就是瀏覽器的事件機制了。
這里就應該是initMouseEvent之后,瀏覽器干的事情,來尋找是否有target來響應此次事件,如果前面一直沒有target來響應,最后就會到window上,一般來說我們不會在window上做事件處理,就會沒有任何響應,事件結束了。如果碰巧的事,此時有target(一般來說就是element了)來響應,那么就會執行綁定的函數了。
總結下整個流程:用戶點擊屏幕,300ms之內,瀏覽器攔截下這個行為,沒有去真正觸發相關element上綁定的click事件執行函數,而是記錄操作相關數據,等待接下來的操作,由于我們使用zepto庫綁定了tap事件,事件中有監聽touchend觸發了,立刻執行相關操作,隱藏了彈層。300ms到了,瀏覽器認為這次動作是click而不是dbclick,然后init一次mouseEvent在相同的屏幕位置,接著開始事件機制,發現相同位置有一個element綁定了click處理函數,執行這個函數,Over!!!穿透就是這樣產生的。PS:瀏覽器行為部分是猜測,未驗證。
至于解決方案:網上有很多,目前最好的是fastclick,不過fastclick也會有其他問題,例如在滑動中點擊之類的。另外就是用zepto但是要preventDefault。
Android自己chrome已經解決了,可以用其他方式,官方文檔,目前Safari也支持了,不過是在高版本上,相關討論可以看fastclick的issue
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/50440.html
摘要:瀏覽器自動響應后續處理。瀏覽器行為部分是猜測,未驗證。至于解決方案網上有很多,目前最好的是,不過也會有其他問題,例如在滑動中點擊之類的。 問題來源 年前去阿里面試,過程中說道了fastclick解決iPhone機器上300ms點擊延遲的問題,然后就被問到了zepto的點擊穿透的現象以及產生這個具體原因,當時回答的不是很好,主要是沒有特別深入的去研究這個原因,只是知道有這個現象和問題,大...
摘要:分別存儲事件的定時器。事件定時器延時時間存儲事件對象滑動方向判斷我們根據下圖以及對應的代碼來理解滑動的時候方向是如何判定的。取消長按,以及取消所有事件取消長按取消所有事件方式都是類似,先調用取消定時器,然后釋放對應的變量,等候垃圾回收。 前言 移動端原生支持touchstart、touchmove、touchend等事件,但是在平常業務中我們經常需要使用swipe、tap、double...
摘要:使用移動設備查看頁面時會發現,在微信瀏覽器中有頂部導航欄有效解決圖片使用單位邊角缺失的問題前端掘金起因在移動端使用布局時圖片也需要用單位。移動端實踐前端掘金說起,相信大家并不陌生。 Sticky Footer,完美的絕對底部 - 前端 - 掘金寫在前面 做過網頁開發的同學想必都遇到過這樣尷尬的排版問題:在主體內容不足夠多或者未完全加載出來之前,就會導致出現(圖一)的這種情況,原因是因為...
閱讀 1207·2021-09-03 10:44
閱讀 604·2019-08-30 13:13
閱讀 2796·2019-08-30 13:11
閱讀 1967·2019-08-30 12:59
閱讀 1034·2019-08-29 15:32
閱讀 1595·2019-08-29 15:25
閱讀 987·2019-08-29 12:24
閱讀 1277·2019-08-27 10:58