1. 300ms延遲的產(chǎn)生緣由
移動(dòng)端瀏覽器的默認(rèn)顯示寬度是980px(不同機(jī)型各異,但相差不大)侄柔,而不是屏幕的寬度(320px或其他)梯影。為了對(duì)早期普通網(wǎng)頁(yè)更好的體驗(yàn),iphone設(shè)計(jì)了雙擊放大顯示的功能--這就是300ms延遲的來(lái)源:如果用戶一次點(diǎn)擊后300ms內(nèi)沒有其他操作领舰,則認(rèn)為是個(gè)單擊行為;否則為雙擊放大行為迟螺。
2. 點(diǎn)透行為
假設(shè)有兩個(gè)層級(jí)冲秽,A和B;A在上面矩父,B在下面锉桑。 如果A監(jiān)聽touch事件(zepto的tap事件),而且B上有個(gè)鏈接(或者監(jiān)聽click事件)窍株,那么當(dāng)touch A后民轴,先后觸發(fā)了touchStart和touchEnd事件,touchEnd后A層隱藏球订,而此刻會(huì)觸發(fā)在document最前面B的click事件后裸;這就是點(diǎn)透行為。
3. 解決方法
- 設(shè)置不能縮放:
user-scalable=no
冒滩。 不能縮放就不會(huì)有雙擊縮放操作微驶,因此click事件也就沒了300ms延遲,這個(gè)是Chrome首先在Android中提出的开睡。 - 設(shè)置顯示寬度:
width=device-width
因苹。Chrome 開發(fā)團(tuán)隊(duì)不久前宣布,在 Chrome 32 這一版中篇恒,他們將在包含 width=device-width 或者置為比 viewport 值更小的頁(yè)面上禁用雙擊縮放扶檐。當(dāng)然,沒有雙擊縮放就沒有 300 毫秒點(diǎn)擊延遲婚度。 - IE的指針事件 (Pointer Events):設(shè)置
touch-action:none
蘸秘,根據(jù)規(guī)范,touch-action 屬性決定 “是否觸摸操作會(huì)觸發(fā)用戶代理的默認(rèn)行為蝗茁。這包括但不限于雙指縮放等行為”醋虏。
從實(shí)際應(yīng)用的角度來(lái)看,touch-action決定了用戶在點(diǎn)擊了目標(biāo)元素之后哮翘,是否能夠進(jìn)行雙指縮放或者雙擊縮放颈嚼。因此,這也相當(dāng)完美地解決了 300 毫秒點(diǎn)擊延遲的問(wèn)題饭寺。
鑒于上述的3種解決方案阻课,現(xiàn)在較為通用的meta設(shè)置為:
<meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
4. 現(xiàn)在的流行解決方案:
上述的3種解決方案可以解決Chrome Android和IE10+下的300ms問(wèn)題叫挟,但是對(duì)其他瀏覽器還需要特定的解決方案。
- 指針事件的 polyfill
指針事件的 polyfill 比較多限煞,以下列出比較流行的幾個(gè)抹恳。Google 的 Polymer,微軟的 HandJS和@Rich-Harris 的 Points - FastClick
FastClick 是 FT Labs 專門為解決移動(dòng)端瀏覽器 300 毫秒點(diǎn)擊延遲問(wèn)題所開發(fā)的一個(gè)輕量級(jí)的庫(kù)署驻。簡(jiǎn)而言之奋献,F(xiàn)astClick 在檢測(cè)到 touchend事件的時(shí)候,會(huì)通過(guò) DOM 自定義事件立即觸發(fā)一個(gè)模擬click事件旺上,并把瀏覽器在 300 毫秒之后真正觸發(fā)的 click事件阻止掉瓶蚂。
5. FastClick
現(xiàn)階段FastClick被更多使用,借助它通過(guò)監(jiān)聽click事件宣吱,即可消除300ms的問(wèn)題窃这。
通過(guò)閱讀源碼可知:
- FastClick通過(guò)判斷瀏覽器類型決定其是不是需要執(zhí)行,下面幾種場(chǎng)景下不會(huì)執(zhí)行FastClick邏輯:
- 不支持
ontouchstart
事件的瀏覽器 - Android Chrome 或者 firefox27以上 設(shè)置了
user-scalable="no"
- 滿足特定要求的 IE10+ 瀏覽器
- 部分黑莓瀏覽器
- 注冊(cè)了touchStart征候、touchEnd等事件杭攻,監(jiān)聽touchStart決定事件對(duì)象的target、時(shí)間倍奢、位置等信息朴上;通過(guò)touchEnd得到touch的結(jié)束時(shí)間垒棋。如果touch時(shí)長(zhǎng)大于700ms卒煞,則是長(zhǎng)按事件;如果連續(xù)兩次touchEnd的時(shí)間間隔小于200ms叼架,那么認(rèn)定為快速點(diǎn)擊畔裕,特殊對(duì)待;排除上面兩張情況乖订,就通過(guò)
clickEvent = document.createEvent('MouseEvents'); initMouseEvent; dispatchEvent
手動(dòng)觸發(fā)click事件扮饶。