核心目的是提升滚动流畅度,因浏览器可跳过等待JS执行而立即响应默认行为;必须加passive的场景包括监听touchstart/touchmove/wheel/scroll且不调用preventDefault();Vue中用@event.passive语法,不可与.prevent共存。

在 Vue 模板中给触摸或滚动事件添加 passive 选项,核心目的是告诉浏览器:这个事件处理器**不会调用 preventDefault()**,因此浏览器可以跳过等待 JS 执行的等待阶段,立即响应默认行为(比如滚动、缩放),从而显著提升滚动流畅度。
什么时候必须加 passive
当监听的是 touchstart、touchmove、wheel 或 scroll 这类高频触发且常伴随默认行为的事件时,尤其在移动端或长列表场景下:
- 用户手指在列表上滑动时,页面要同步滚动 —— 但你的处理函数只做位置计算、不阻止滚动
- 实现自定义下拉刷新,但仅监听 touchstart/touchmove 来判断下拉距离,真正触发刷新前并不阻止默认滚动
- 做手势识别(如左右滑切换页),但希望原生滚动仍能正常工作
Vue 模板中怎么写
直接在事件修饰符里加 .passive,语法简洁明确:
<div @touchmove.passive="handleTouchMove"></div>
立即学习“前端免费学习笔记(深入)”;
<ul @wheel.passive="onWheel"></ul>
注意:.passive 不能和 .prevent 同时使用,因为语义冲突 —— 你既说“不会阻止默认行为”,又说“要阻止”,浏览器会忽略 .prevent 或报错。
Vue 3 组合式 API 与 最佳实践,涵盖代码组织、useXxx 模式、组合式函数设计、Store 集成、响应式优化及功能抽取。
哪些情况不能加 passive
一旦你在事件处理函数里调用了 event.preventDefault()(比如阻止页面滚动来实现吸顶、拦截缩放、禁用双指放大),就必须去掉 .passive,否则调用会静默失败,且控制台会报警告:
- 下拉刷新中,当满足条件后调用
event.preventDefault()阻止继续滚动 - 自定义滚动容器,需要完全接管 touchmove 并禁止原生滚动
- 手势拖拽元素,同时要禁用页面跟随移动
这种场景建议改用 addEventListener 手动绑定,并显式传入 { passive: false },避免 Vue 模板修饰符的限制。
搭配 .prevent 和 .stop 要小心
.passive 本身不阻止事件冒泡或默认行为,它只是向浏览器声明“我不会阻止”。如果你还需要阻止冒泡,可以叠加 .stop;但不能再叠加 .prevent:
<div @touchmove.passive.stop="handleMove"></div> ✅ 可行
<div @touchmove.passive.prevent="handleMove"></div> ❌ 无效且可能报错
如果真需要 prevent + passive 的效果,说明逻辑有矛盾,应重新设计:要么放弃阻止,默认行为交给浏览器;要么放弃 passive,接受轻微卡顿并手动控制。


















