必须在监听@scroll、@touchmove且不调用preventdefault()时添加.passive修饰符,如懒加载、吸顶判断;冲突场景需移除该修饰符,配合css优化滚动性能。

在移动端开发中,给滚动容器(如 div 或 body)绑定 scroll、touchmove 等事件时,浏览器默认会等待 JavaScript 执行完才继续滚动,导致卡顿。使用 .passive 修饰符可告诉浏览器:“这个事件处理器**永远不会调用 preventDefault()**”,从而启用原生滚动加速,显著提升流畅度。
什么时候必须加 .passive?
以下场景建议强制添加:
- 监听
@scroll、@touchmove但仅做节流读取位置(如懒加载、吸顶判断),不阻止默认行为 - Vue 中使用
v-on:touchmove.passive替代原生addEventListener手动配置 - 滚动区域嵌套(如弹窗内可滚动列表),父级滚动需保持响应性
Vue 中的正确写法(2.x / 3.x 通用)
直接在指令后追加 .passive,无需额外逻辑:
<!-- ✅ 正确:浏览器可立即滚动 --> <div></div> <p><!-- ✅ 滚动监听(只读位置)--> </p><div class="scroll-container"></div><p><!-- ❌ 错误:若内部调用 preventDefault(),.passive 会失效且控制台报错 --> </p><div></div>
不能和 .passive 共存的情况
以下操作与 .passive 冲突,必须移除修饰符或改用其他方案:
- 需要阻止滚动(如模态框打开时禁止背景滚动)→ 改用
overflow: hidden或动态设置touch-action: none - 自定义下拉刷新、拖拽排序 → 使用
.prevent或原生addEventListener显式传{ passive: false } - 监听
mousewheel(PC 端)→.passive无效,PC 滚轮无此限制
配合 CSS 提升效果
单靠 .passive 不够,还需优化渲染层:
- 给滚动容器添加
will-change: scroll-position(谨慎使用,仅对高频滚动区) - 避免在
scroll回调中触发重排(如读取offsetTop后立即改样式),优先用getBoundingClientRect()+requestAnimationFrame - 移动端确保容器有明确高度和
overflow-y: auto,避免触发全局body滚动










