今天碰到一個關於行動裝置選單的問題,使用者在操作選單時,如何能夠避免主內容被捲動,維持在目前的瀏覽位置。

桌面版很容易搞定,當選單狀態啟用時,使用 CSS 將 body overflow: hidden 即可;

重點在於使用行動裝置時,桌面版的設定不管用,如果硬要使用 CSS 去做,背景固然可以鎖定,但也會回到頁面最頂端,與 position: fixed 一樣,只好將腦筋動到行動裝置的事件上,如果可以禁用手機某些 DOM 的滾動事件呢?

姑狗了半天最後終於試出解法:

function disableMove() {
    event.preventDefault();
}

//禁用行動裝置手指移動的動作
document.addEventListener('touchmove', disableMove, {passive: false});

//取消禁用
document.removeEventListener('touchmove', disableMove);

由於行動裝置上我們無法去禁用視窗的滾動事件,只好從裝置特有的 touch 事件下手,與滾動相關的操作就是 touchmove 了,唯有當手指碰觸螢幕並 “移動” 才會達到滑鼠滾動的效果,透過在設定條件達成時去禁用 DOM 的 touchmove,就可以做到鎖定捲動的效果,但問題總是沒這麼簡單,一般監聽事件的時候,想要取消預設動作,event.preventDefault() 下去就對了,偏偏用在這邊卻沒反應。

 

事件監聽的新屬性參數

關鍵點在於範例中監聽事件的最後一個選項,原本在 DOM 規則中負責處理事件冒泡的第 3 個參數針對行動裝置有了新的屬性:

addEventListener(type, listener, {
    capture: false,
    passive: false,
    once: false
})
  • capture:
    Boolean 值,與監聽動作的舊參數一樣,決定事件的冒泡。
  • passive:
    Boolean 值,被動事件監聽器,預設值為 true 代表不會禁用預設事件,false 則相反。
  • once:
    Boolean 值,代表該事件為一次性,執行完成後自動 removeEventListener,目前好像還沒有瀏覽器支援。

 

passive 是這篇筆記的重點,這個屬性是為了行動裝置的流暢度而誕生的,透過將屬性值設為 true 可以提升裝置在瀏覽頁面的流暢度,缺點是,如果設為 true 則預設的動作無法被停用,則 event.preventDefault() 無效,只有設為 false 才可以達到阻止預設動作的效果,下面放一個影片,是關於有無設定 passive 屬性的流暢性差別。

 

發表迴響

你的電子郵件位址並不會被公開。 必要欄位標記為 *

這個網站採用 Akismet 服務減少垃圾留言。進一步瞭解 Akismet 如何處理網站訪客的留言資料