React阻止Ctrl滚轮缩放代码中passive参数作用详解
禁止Ctrl+滚轮缩放代码中passive配置项作用解析
问题对应的实现代码如下:
import { useEffect } from "react"; import "./styles.css"; export default function App() { useEffect(() => { const handleWheel = (e) => { if (e.ctrlKey || e.metaKey) e.preventDefault(); console.log(e); }; window.addEventListener("wheel", handleWheel, { passive: false }); return () => { window.removeEventListener("wheel", handleWheel, { passive: true }); }; }, []); return ( <div className="App"> <div className="hover">Hover me </div> </div> ); }
绑定事件时传入{ passive: false }的作用
- 现代浏览器为了优化滚动、滚轮类事件的响应速度,针对
window、document这类顶层节点注册的wheel、touchstart、touchmove事件,默认会把passive值设为true。 - 当
passive为true时,浏览器会默认事件回调里绝对不会调用e.preventDefault()阻止默认行为,不等JS回调执行完就会直接触发默认的滚动、缩放逻辑,避免JS执行阻塞页面交互造成卡顿。这种情况下如果硬要在回调里调用e.preventDefault(),不仅拦不住默认行为,控制台还会抛出「被动事件监听器内无法阻止默认行为」的警告。 - 这段代码的核心目的就是拦截Ctrl/Command+滚轮触发的页面缩放,必须靠
e.preventDefault()才能生效,所以必须显式传{ passive: false },告诉浏览器别着急执行默认行为,等回调跑完再判断要不要触发默认逻辑,这样拦截缩放的代码才能正常生效。
移除事件时传入{ passive: true }的作用
- DOM标准里对事件移除的匹配规则很明确:
removeEventListener找之前注册的监听器时,只校验三个条件:事件名一致、回调函数引用一致、capture(是否在捕获阶段触发)配置一致,passive、once这类配置项根本不参与匹配。 - 说白了这里传的
{ passive: true }没有任何实际作用,属于开发者写的时候的认知偏差——误以为移除事件要和绑定时传完全一样的配置才加了这个值。实际运行的时候,不管你这里传不传passive、传true还是false,只要capture值和绑定的时候一致(这里都是默认的false),都能正常把绑定的handleWheel回调删掉。 - 这段卸载代码如果要写得规范,直接传和绑定时一致的
{ passive: false },或者干脆不传第三个参数都可以,传{ passive: true }虽然不影响功能,但属于没必要的冗余写法。
内容的提问来源于stack exchange,提问作者kartikay dwivedi
相关产品推荐
相关产品推荐

