摘要:瀏覽器自動響應(yīng)后續(xù)處理。瀏覽器行為部分是猜測,未驗(yàn)證。至于解決方案網(wǎng)上有很多,目前最好的是,不過也會有其他問題,例如在滑動中點(diǎn)擊之類的。
問題來源
年前去阿里面試,過程中說道了fastclick解決iPhone機(jī)器上300ms點(diǎn)擊延遲的問題,然后就被問到了zepto的“點(diǎn)擊穿透”的現(xiàn)象以及產(chǎn)生這個具體原因,當(dāng)時回答的不是很好,主要是沒有特別深入的去研究這個原因,只是知道有這個現(xiàn)象和問題,大概怎么解決,面試完了之后有一天突然想起來了,就決定仔細(xì)的研究下。
其實(shí)有好多文章都寫了,內(nèi)容有很多我就不重復(fù),總結(jié)以下幾點(diǎn):
300ms延遲是由于瀏覽器要判斷是單機(jī)還是雙擊造成的延遲處理點(diǎn)擊事件
fastclick解決方式用touchstart結(jié)合touchmove以及touchend替代click事件
zepto的tap會“擊穿”頁面是由于既響應(yīng)了自身的tap(也就是touch事件),又沒有攔截掉原來的click事件,導(dǎo)致重復(fù)執(zhí)行了2次事件,在有遮罩彈層的時候就會出現(xiàn)“擊穿”效果。如果不太明白的話看這篇文章zepto的擊穿
年前探究當(dāng)時研究到這里時候我有一個大大的疑問就是為什么click延遲執(zhí)行之后,遮罩層下面的頁面的click事件會被觸發(fā),我明明點(diǎn)擊的遮罩層的A按鈕,為何下面頁面的B按鈕的事件會執(zhí)行。按照我最初的想法,應(yīng)該是繼續(xù)執(zhí)行A按鈕的事件?。。?!此時我內(nèi)心是這樣的
于是我開始探究這個問題,我搜了下大概的資料,基本都沒有講這個具體原因的,也許是我打開方式不對,反正沒有找到,無奈之下,我只能翻看fastclick的源碼來看它為何沒有出現(xiàn)這個問題,然后看到了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,當(dāng)時就在想肯定和mouseEvent執(zhí)行的原理有關(guān)了,到這個階段算是有了眉目。
接著搞緊接著,開始過年,過年期間享受了生活,并沒有碰代碼和文檔(好墮落的感覺......),加上我跳槽的空檔和折騰,年后稍稍穩(wěn)定下來了,最近又想起了年前這探究一半的猜想,開始繼續(xù)搞了起來,順便收收心,好進(jìn)入狀態(tài)。
先說猜想--click事件最開始其實(shí)在瀏覽器當(dāng)中被捕捉的時候,只有mouseEvent的相關(guān)屬性,也就是我們平常在console.log(event)的一部分,之后,瀏覽器才會結(jié)合html,js產(chǎn)生我們常說的click時間,接著觸發(fā)我們使用js綁定的函數(shù)。
基于這個猜想,我開始翻閱mozilla和W3C的文檔來了解mouseEvent。
翻看文檔之后發(fā)現(xiàn)mouseEvent果然只有 screenX,screenY,clientX,clientY,ctrlKey,altKey,shiftKey,metaKey,button,buttons,EventTarget?relatedTarget。
其中button和buttons指的是鼠標(biāo)的按鈕類型,就是左鍵,右鍵,滾輪這些。用數(shù)字代替,0表示左鍵,1是滾輪,2是右鍵,其他更多功能鍵,都是大于2的。
從上面我們能看出來,其實(shí)對于mouseEvent而言,它只知道我們在屏幕的哪個位置,做了什么動作(鼠標(biāo)操作),并不知道是在哪個element上面。這也就是fastclick還原用戶點(diǎn)擊事件最后做的事情。
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
初始化一個鼠標(biāo)事件,然后dispatch這個鼠標(biāo)事件。瀏覽器自動響應(yīng)后續(xù)處理。
接著來看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來承載這次鼠標(biāo)事件。一般來說target要么是element要么是document,如果都沒有那么就是window對象了。到這里大家應(yīng)該就比較明白,這里就是瀏覽器的事件機(jī)制了。
這里就應(yīng)該是initMouseEvent之后,瀏覽器干的事情,來尋找是否有target來響應(yīng)此次事件,如果前面一直沒有target來響應(yīng),最后就會到window上,一般來說我們不會在window上做事件處理,就會沒有任何響應(yīng),事件結(jié)束了。如果碰巧的事,此時有target(一般來說就是element了)來響應(yīng),那么就會執(zhí)行綁定的函數(shù)了。
總結(jié)下整個流程:用戶點(diǎn)擊屏幕,300ms之內(nèi),瀏覽器攔截下這個行為,沒有去真正觸發(fā)相關(guān)element上綁定的click事件執(zhí)行函數(shù),而是記錄操作相關(guān)數(shù)據(jù),等待接下來的操作,由于我們使用zepto庫綁定了tap事件,事件中有監(jiān)聽touchend觸發(fā)了,立刻執(zhí)行相關(guān)操作,隱藏了彈層。300ms到了,瀏覽器認(rèn)為這次動作是click而不是dbclick,然后init一次mouseEvent在相同的屏幕位置,接著開始事件機(jī)制,發(fā)現(xiàn)相同位置有一個element綁定了click處理函數(shù),執(zhí)行這個函數(shù),Over?。?!穿透就是這樣產(chǎn)生的。PS:瀏覽器行為部分是猜測,未驗(yàn)證。
至于解決方案:網(wǎng)上有很多,目前最好的是fastclick,不過fastclick也會有其他問題,例如在滑動中點(diǎn)擊之類的。另外就是用zepto但是要preventDefault。
Android自己chrome已經(jīng)解決了,可以用其他方式,官方文檔,目前Safari也支持了,不過是在高版本上,相關(guān)討論可以看fastclick的issue
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/81557.html
摘要:瀏覽器自動響應(yīng)后續(xù)處理。瀏覽器行為部分是猜測,未驗(yàn)證。至于解決方案網(wǎng)上有很多,目前最好的是,不過也會有其他問題,例如在滑動中點(diǎn)擊之類的。 問題來源 年前去阿里面試,過程中說道了fastclick解決iPhone機(jī)器上300ms點(diǎn)擊延遲的問題,然后就被問到了zepto的點(diǎn)擊穿透的現(xiàn)象以及產(chǎn)生這個具體原因,當(dāng)時回答的不是很好,主要是沒有特別深入的去研究這個原因,只是知道有這個現(xiàn)象和問題,大...
摘要:分別存儲事件的定時器。事件定時器延時時間存儲事件對象滑動方向判斷我們根據(jù)下圖以及對應(yīng)的代碼來理解滑動的時候方向是如何判定的。取消長按,以及取消所有事件取消長按取消所有事件方式都是類似,先調(diào)用取消定時器,然后釋放對應(yīng)的變量,等候垃圾回收。 前言 移動端原生支持touchstart、touchmove、touchend等事件,但是在平常業(yè)務(wù)中我們經(jīng)常需要使用swipe、tap、double...
摘要:使用移動設(shè)備查看頁面時會發(fā)現(xiàn),在微信瀏覽器中有頂部導(dǎo)航欄有效解決圖片使用單位邊角缺失的問題前端掘金起因在移動端使用布局時圖片也需要用單位。移動端實(shí)踐前端掘金說起,相信大家并不陌生。 Sticky Footer,完美的絕對底部 - 前端 - 掘金寫在前面 做過網(wǎng)頁開發(fā)的同學(xué)想必都遇到過這樣尷尬的排版問題:在主體內(nèi)容不足夠多或者未完全加載出來之前,就會導(dǎo)致出現(xiàn)(圖一)的這種情況,原因是因?yàn)?..
摘要:借著產(chǎn)品層面的功能和視覺升級,我們用對它進(jìn)行了一次技術(shù)重構(gòu)。前端優(yōu)化是一個讓人技術(shù)提升的,希望你也能從這里學(xué)到一些東西。年最流行的前端鏈接我們每周會給多名前端開發(fā)者發(fā)送新聞郵件。 面試 -- 網(wǎng)絡(luò) HTTP 現(xiàn)在面試門檻越來越高,很多開發(fā)者對于網(wǎng)絡(luò)知識這塊了解的不是很多,遇到這些面試題會手足無措。本篇文章知識主要集中在 HTTP 這塊。文中知識來自 《圖解 HTTP》與維基百科,若有錯...
閱讀 2372·2021-11-24 10:31
閱讀 3427·2021-11-23 09:51
閱讀 2239·2021-11-15 18:11
閱讀 2387·2021-09-02 15:15
閱讀 2452·2019-08-29 17:02
閱讀 2285·2019-08-29 15:04
閱讀 831·2019-08-29 12:27
閱讀 2853·2019-08-28 18:15