簡要的探討一下移動端 touch 事件處理幾個坑,以及相應的簡單處理方法。git
假設有個彈出層,上面有個關閉的按鈕支持 touchend 觸發後關閉,若正好下方有個元素支持 click 事件,在彈出層關閉後將會在下方元素觸發 click 事件。這種效果確定不是咱們須要的,並且咱們沒法肯定合適會在上方出現一個支持 touch 的彈出層,因此我認爲最好的處理方式是禁用全部元素的 click 事件,相比 click 須要長達 1s 的觸發時間,使用 touchend 能夠得到更好的體驗。github
一個正確的 tap 事件應當知足一下條件:web
具體實現代碼能夠參考 tap-event。app
Android 4.0 如下是不支持原生的 webview 滾動的,因此只能使用 iscroll 之類的工具來模擬元素滾動。它的缺點就是有些過於的複雜,因此我仍是會在條件容許的狀況下使用原生的滾動。函數
啓用原生滾動只須要給外層元素加上樣式 -webkit-overflow-scrolling: touch;
便可,若是你的監聽函數比較佔用資源咱們能夠經過一個簡單的 buffer 函數來限制它的觸發間隔,例如:工具
function buffer(fn, ms) { var timeout; return function() { if (timeout) return; var args = arguments; timeout = setTimeout(function() { timeout = null; fn.apply(null, args); }, ms); } } document.querySelector('.scrollable').onscroll = buffer(onScroll, 100);
另外的建議就是不要在可滾動元素上使用陰影樣式(text-shadow 和 box-shadow),由於它們很是影響性能,並且看上去也不怎麼美觀。性能
還有須要注意的是若是你須要啓用apple-mobile-web-app-capable
, 注意將apple-mobile-web-app-status-bar-style
設置爲black-translucent
,不然會出現還差 22 像素滾動不到頭的坑爹 bug。code
IOS下默認狀況下用戶的拖動操做在scroll滾到頭之後會致使總體頁面的滾動,一種方式是禁用掉 document 的 touchmove 原生觸發component
document.addEventListener('touchmove', function(e) { e.preventDefault(); });
此時原生的滾動是沒法工做的,解決辦法就是禁用滾動元素的 touchmove 事件冒泡事件
scrollable.addEventListener('touchmove', function (e) { e.stopPropagation(); });
另外一種方式是斷定滾動元素滾到頭以後禁用掉默認的處理
var el = document.querySelector('.scrollable'); var sy = 0; events.bind(el, 'touchstart', function (e) { sy = e.pageY; }) events.bind(el, 'touchmove', function (e) { var down = (e.pageY - sy > 0); //top if (down && el.scrollTop <= 0) { e.preventDefault(); } //bottom if (!down && el.scrollTop >= el.scrollHeight - el.clientHeight) { e.preventDefault(); } })
我我的傾向於第二種方案,由於若是單純的禁用 document 的 touchmove 監聽,會致使一些處理的失效,好比說上面提到的 tap-event
模塊。
經過 event 的 pageX 和 pageY 屬性便可計算,可參考 hammer.js