js中用passive优化滚动性能的核心是声明事件监听器永不调用preventdefault(),从而跳过同步等待、提升响应流畅度;适用于仅读取滚动位置的touchmove/scroll监听,尤其自定义滚动容器和移动端手势区域。

在 JS 中用 passive 配置项优化滚动事件性能,核心是告诉浏览器:“这个事件监听器**绝不会调用 preventDefault()**”,从而跳过同步等待环节,让滚动立即响应、丝滑不卡顿。
什么时候必须加 { passive: true }?
以下场景强烈建议显式添加:
- 监听
touchmove或scroll,仅用于读取位置(如判断是否吸顶、是否接近底部) - 滚动容器是自定义区域(非
body),比如弹窗内的列表、侧边栏内容区 - 移动端页面中所有可能参与手势滚动的元素,尤其是
div、section等滚动容器
怎么正确写?两种常用方式
方式一:原生 addEventListener(推荐显式声明)
const container = document.querySelector('.scroll-list');
container.addEventListener('touchmove', handleTouchMove, { passive: true });
container.addEventListener('scroll', handleScroll, { passive: true });
方式二:Vue 模板中使用 .passive 修饰符(2.x / 3.x 通用)
<div></div> <div class="scroll-container"></div>
⚠️ 注意:一旦加了 passive: true,回调里就不能再调用 e.preventDefault(),否则控制台会报错且行为被忽略。
哪些情况不能加?要主动移除
遇到以下需求时,passive 不适用,必须改用其他方案:
- 需要禁止背景滚动(如模态框弹出时)→ 改用
document.body.style.overflow = 'hidden'或touch-action: none - 实现下拉刷新或拖拽排序 → 显式传
{ passive: false },并配合.prevent或手动调用preventDefault() - 监听
wheel(PC 滚轮)→passive对其无效,无需添加
搭配 CSS 才更有效
单靠 passive 只解决“阻塞”问题,滚动流畅还需渲染层配合:
- 给滚动容器设置明确高度和
overflow-y: auto,避免意外触发body滚动 - 慎用
will-change: scroll-position,只对高频滚动区启用(如长列表) - 滚动回调中避免读写布局属性(如
offsetTop、clientHeight后立刻改样式),优先用getBoundingClientRect()+requestAnimationFrame











