passive: true 能提升滚动流畅度,因浏览器无需等待JS执行即可触发默认滚动;但监听器内不可调用 preventDefault(),否则报错。

在 JavaScript 中给滚动事件(scroll、touchstart、wheel 等)添加 passive: true 选项,能显著提升滚动流畅度,尤其在移动端。它的核心作用是告诉浏览器:“这个事件处理器**不会调用 preventDefault()**”,从而让浏览器无需等待 JS 执行完毕就可立即触发默认滚动行为。
为什么 passive 能优化性能?
默认情况下,浏览器必须等所有注册的事件监听器执行完,才能确定是否要阻止默认滚动(比如阻止页面滚动来实现自定义下拉刷新)。这会强制浏览器进入“同步等待”状态,导致滚动卡顿。启用 passive: true 后,浏览器跳过等待,直接滚动,JS 监听器在后台异步执行——滚动丝滑了,但你也**不能再在该监听器里调用 preventDefault()**,否则控制台会报错(Chrome/Firefox 均有警告)。
如何正确添加 passive 选项
使用 addEventListener 时,第三个参数传入配置对象:
element.addEventListener('scroll', handler, { passive: true });
立即学习“Java免费学习笔记(深入)”;
常见写法示例:
- 监听窗口滚动:
window.addEventListener('scroll', onScroll, { passive: true }); - 监听容器滚动:
container.addEventListener('scroll', onContainerScroll, { passive: true }); - 监听触摸开始(常用于手势识别):
element.addEventListener('touchstart', onTouchStart, { passive: true });
哪些场景适合用 passive: true?
只要你的事件处理函数不阻止默认行为,就适合开启:
- 滚动节流(throttle)更新吸顶导航、视差效果、懒加载判断
- 记录用户滚动位置或行为埋点
- 触控开始时仅做坐标记录,不拦截滚动
⚠️ 反例:实现下拉刷新、自定义滚动条拖拽、阻止页面滚动的弹窗遮罩——这些必须调用 preventDefault(),就不能设 passive: true;若仍想优化,可改用 { passive: false } 显式声明(但无性能收益),或换用 touchmove + preventDefault 配合 CSS touch-action 属性精细控制。
兼容性与安全写法
现代浏览器均支持 passive(Chrome 51+、Firefox 49+、Safari 11.1+、Edge 79+)。为避免旧版报错,可用特性检测封装:
const supportsPassive = () => {<br> let supports = false;<br> try {<br> const opts = Object.defineProperty({}, 'passive', {<br> get() { supports = true; }<br> });<br> window.addEventListener('test', null, opts);<br> } catch (e) {}<br> return supports;<br>};<br><br>element.addEventListener('scroll', handler, { passive: supportsPassive() });



















