js 阻止默认事件怎么写
说明用 e.preventDefault() 阻止默认事件,return false 仅在 jQuery 和内联 onclick 中生效,并指出 passive 监听等导致失效的原因及 {passive:false} 解法。
在 JavaScript 中阻止默认事件只用一行:e.preventDefault()。要注意的是,在 addEventListener 的回调里 return false 不生效,只有 jQuery 事件方法和 HTML 内联 onclick="return false" 才等价于「阻止默认行为 + 阻止冒泡」。
event.preventDefault() 怎么写?
结论:在事件处理函数里执行 e.preventDefault() 即可,位置放在逻辑最前面,避免后面的代码抛错导致没执行到。
document.querySelector('#myForm').addEventListener('submit', (e) => {
e.preventDefault(); // 阻止表单提交后的页面跳转
const data = new FormData(e.target);
fetch('/api/save', { method: 'POST', body: data });
});
三点细节:
- 参数
e是事件对象,忘记接收参数(写成() => {})是最常见的报错来源。 preventDefault()没有返回值,不需要e.preventDefault() === true这类判断。- 阻止后事件的「默认行为」被取消,但事件本身仍会继续冒泡,兄弟元素的监听器照常触发。
return false 能不能阻止默认事件?
结论:分场景。jQuery 的 return false 等价于同时执行 preventDefault() 和 stopPropagation();HTML 内联 onclick="return false" 可以阻止默认行为;原生 addEventListener 里 return false 完全无效,这是新手最常踩的坑。
<a href="https://www.gj0.com/about.html" onclick="return false">点了不跳转</a>
// 无效写法:原生监听器里 return false 等于没写
el.addEventListener('click', (e) => {
return false; // 该跳转还是跳转
});
如果你用的是 onclick 属性赋值(el.onclick = () => false),同样不生效,因为返回值被丢掉了。统一改用 e.preventDefault() 最稳妥。
为什么 preventDefault() 有时候不生效?
结论:九成以上是因为监听器被声明为被动(passive),此时 preventDefault() 会被浏览器忽略并打印警告。Chrome 56 起,touchstart、touchmove 在 window、document、body 上默认 passive: true;Chrome 73 起 wheel 也加入这一默认。解决办法是显式传 { passive: false }:
document.addEventListener('touchmove', (e) => {
e.preventDefault(); // 阻止页面跟着滑动
}, { passive: false });
另外两种失效原因:
- 事件本身不可取消,判断
e.cancelable === false时preventDefault()无效。 - 在
async函数里await之后才调用preventDefault(),此时事件派发流程已结束,调用无效。要么在await前先阻止,要么把阻止逻辑拆到外层同步函数里。
阻止默认行为和阻止冒泡有什么区别?
结论:preventDefault() 管的是「浏览器接下来要做的默认动作」,stopPropagation() 管的是「事件要不要继续传给父元素」,两者互不替代,经常需要一起写。
| 方法 | 作用 | 典型场景 |
|---|---|---|
e.preventDefault() | 取消浏览器默认行为 | 表单提交跳转、链接跳转、右键菜单 |
e.stopPropagation() | 停止向父级冒泡/捕获 | 弹窗内点击不关闭遮罩 |
e.stopImmediatePropagation() | 停止冒泡并阻止同元素后续监听器 | 同一元素绑定多个 click |
注意一个反直觉点:<a> 上阻止了默认跳转,事件仍然会冒泡到 document,父级的点击监听器照样会跑。
表单、链接、右键菜单分别怎么写?
结论:这三类是最高频场景,代码各有固定写法。
阻止表单提交(最常见的重复提交防护):
form.addEventListener('submit', (e) => {
e.preventDefault();
if (!form.checkValidity()) return; // 自己接管校验后再提交
});
阻止链接跳转但保留点击逻辑:
document.querySelectorAll('a[data-action]').forEach((a) => {
a.addEventListener('click', (e) => {
e.preventDefault();
doSomething(a.dataset.action);
});
});
屏蔽右键菜单:
document.addEventListener('contextmenu', (e) => e.preventDefault());
阻止拖拽时选中文本或图片另存为:
el.addEventListener('dragstart', (e) => e.preventDefault());
Vue 和 React 里怎么写?
结论:Vue 用事件修饰符 .prevent 更简洁,React 与原生一致,仍然调用 e.preventDefault()。
Vue 2 和 Vue 3 通用写法:
<form @submit.prevent="onSubmit"></form>
<div @click.stop.prevent="handle"></div>
修饰符顺序会影响效果:.self.prevent 与 .prevent.self 行为不同,前者只在点击自身时阻止,后者会在事件到达元素时先阻止再判断。React 中:
function handleSubmit(e) {
e.preventDefault();
// React 17 起事件池已移除,异步里也能安全访问 e
}
老浏览器还要写 returnValue 吗?
结论:现代浏览器不需要。IE9 及更早版本才需要 e.returnValue = false 作为 preventDefault() 的替代,如今 IE 已停止支持,直接用标准 API 即可。真正需要兼容处理的是 passive 支持差异,可以用下面的检测判断:
let passiveSupported = false;
try {
const opts = Object.defineProperty({}, 'passive', {
get() { passiveSupported = true; return false; }
});
window.addEventListener('test', null, opts);
} catch (err) {}
掌握三句话就够了:**原生监听器用 e.preventDefault() 阻止默认行为;return false 只对 jQuery 和内联 onclick 有效;移动端、滚轮被 passive 拦下时补上 { passive: false }**。写的时候顺手区分开「取消默认行为」和「停止冒泡」,能省下大量排查时间。实践里踩到的新坑,欢迎到 GJ站长论坛 前端开发版块(含 HTML / CSS / JS / Vue / React 子分类)发帖交流,帖子里直接贴最小复现代码最快得到答案,注意发帖冷却 30 秒、回帖冷却 15 秒,未上传头像的账号无法发帖。
转载请注明出处,版权归原作者所有。