Unable to preventDefault inside passive event listener due to target being treated as passive.
理解為:
由于瀏覽器必須要在執(zhí)行事件處理函數(shù)之后拳昌,才能知道有沒有掉用過 preventDefault() ,這就導(dǎo)致了瀏覽器不能及時(shí)響應(yīng)滾動(dòng)钠龙,略有延遲。
所以為了讓頁面滾動(dòng)的效果比較順暢御铃,從 chrome56 開始碴里,在 window、document 和 body 上注冊的 touchstart 和 touchmove 事件處理函數(shù)上真,會(huì)默認(rèn)為是 passive: true咬腋。瀏覽器忽略 preventDefault() 就可以第一時(shí)間滾動(dòng)了。
舉例:
wnidow.addEventListener('touchmove', func) 效果和下面一句一樣
wnidow.addEventListener('touchmove', func, { passive: true })
這就導(dǎo)致了一個(gè)問題:
如果在 window睡互、document 和 body的 touchstart 和 touchmove 事件處理函數(shù)中調(diào)用 e.preventDefault() 根竿,會(huì)被瀏覽器忽略掉,并不會(huì)阻止默認(rèn)行為就珠。
如下使用時(shí)控制臺會(huì)報(bào)錯(cuò):
body {
margin: 0;
height: 2000px;
background: linear-gradient(to bottom, red, green);
}
// 在 chrome56 中寇壳,照樣滾動(dòng),而且控制臺會(huì)有提示妻怎,blablabla
window.addEventListener('touchmove', e => e.preventDefault())
解決辦法:
1壳炎、注冊處理函數(shù)時(shí),用如下方式逼侦,明確聲明為不是被動(dòng)的
window.addEventListener('touchmove', func, { passive: false })
2匿辩、應(yīng)用 CSS 屬性 touch-action: none; 這樣任何觸摸事件都不會(huì)產(chǎn)生默認(rèn)行為,但是 touch 事件照樣觸發(fā)榛丢。
touch-action 還有很多選項(xiàng)铲球,詳細(xì)請參考touch-action