跳到主要內容
← 回到學習

學習 · 前端基礎

監聽 passive 屬性

目錄 · 4 個段落
  1. 01為什麼需要 passive
  2. 02何時用 / 不用
  3. 03現代瀏覽器的預設行為
  4. 04實際範例:自訂縮放

監聽 passive 屬性

TL;DR
addEventListener('event', handler, { passive: true }) 告訴瀏覽器「這個 listener 不會 呼叫 preventDefault()」 → 瀏覽器可以 不等 JS 執行完 直接滾動 → 滾動更順、不卡頓。

為什麼需要 passive

當你監聽 wheel / touchstart / touchmove 這類滾動相關事件時,瀏覽器不知道你的 listener 會不會呼叫 preventDefault() 來攔截滾動。

所以瀏覽器只能先暫停滾動,等你的 JS 執行完才繼續 —— 這個延遲就是「滾動卡頓」的元凶。

// ❌ 沒加 passive,瀏覽器必須等這個 listener 跑完才滾動
window.addEventListener('wheel', handleWheel);
 
// ✅ 加 passive,瀏覽器可以平行處理滾動 + JS
window.addEventListener('wheel', handleWheel, { passive: true });
javascript

何時用 / 不用

情境passive
純監聽(分析、追蹤滾動位置)✅ true
需要 e.preventDefault() 阻止預設行為(例:自訂縮放、下拉刷新)❌ false
不確定預設不寫,行為等同 passive: false(較舊瀏覽器)
衝突陷阱
如果在 passive: true 的 listener 裡呼叫 e.preventDefault(),瀏覽器會忽略它 + 在 console 警告: Unable to preventDefault inside passive event listener invocation.

現代瀏覽器的預設行為

Chrome 56+ / Firefox 49+ 起,touchstart 和 touchmove 的 default 已經是 passive: true,除非明確寫 passive: false。wheel 事件預設仍是 non-passive。


實際範例:自訂縮放

需要 preventDefault 才能阻止頁面預設滾動,所以不能用 passive:

canvasEl.addEventListener('wheel', (e) => {
  e.preventDefault();   // 阻止頁面捲動
  zoom(e.deltaY);
}, { passive: false }); // 必須明確設 false
javascript

目錄