passive选项通过告知浏览器监听器永不调用preventdefault(),使浏览器可跳过等待js执行、立即触发原生滚动,从而避免主线程阻塞和滚动卡顿,显著提升移动端touchstart、touchmove、wheel等高频事件的响应性能。

在 JavaScript 中,addEventListener 的 passive 选项能显著提升滚动、触摸等高频事件的响应速度,尤其在移动端。它的核心作用是告诉浏览器:这个事件监听器**永远不会调用 preventDefault()**,因此浏览器可以放心地异步处理滚动,无需等待 JS 执行完毕再更新页面。
为什么 passive 能优化滚动性能?
默认情况下,浏览器必须同步等待所有注册的 touchstart 或 wheel 事件监听器执行完,才能决定是否允许原生滚动(因为 JS 可能调用 preventDefault() 来禁用它)。这会阻塞主线程,导致滚动卡顿、掉帧。启用 passive: true 后,浏览器跳过等待,立即开始滚动,JS 监听器在后台异步执行——用户感知更流畅。
哪些事件适合加 passive: true?
以下事件通常不需阻止默认行为,适合开启 passive:
-
scroll(注意:部分旧版 Chrome 不支持 scroll 的 passive) wheeltouchstarttouchmove
⚠️ 注意:click、keydown 等与用户交互强相关的事件一般不用 passive;若监听器中确实调用了 preventDefault() 却设了 passive: true,浏览器会忽略该调用,并在控制台报错(如 “Unable to preventDefault inside passive event listener”)。
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
如何安全地使用 passive?
推荐用特性检测 + 回退方案,避免兼容性问题:
const opts = typeof AddEventListenerOptions !== 'undefined'
? { passive: true }
: false; // 旧浏览器不支持 options,传 false 表示 useCapture=false
element.addEventListener('touchmove', handler, opts);
更稳妥的做法是封装一个工具函数:
function addPassiveListener(el, type, handler) {
const options = { passive: true };
try {
el.addEventListener(type, handler, options);
} catch (err) {
// 捕获不支持 passive 的错误(如老版 Safari),降级为非 passive
el.addEventListener(type, handler, false);
}
}
现代开发中的实用建议
在框架或业务代码中,可统一约束:
- 对纯滚动监听(如懒加载、视差效果),默认启用
passive: true - 对需要禁止缩放/拖拽的
touchstart,仍用passive: false并显式调用preventDefault() - 借助 Lighthouse 或 Chrome DevTools 的“Rendering”面板观察滚动 FPS,验证优化效果
- Vite / Webpack 构建时,可通过插件自动为已知安全的事件注入 passive(需谨慎评估逻辑)
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










