⭐ 推荐:社区规则条款 V1.0

js 阻止默认事件怎么写

GJ论坛站长
GJ论坛站长 管理员资深会员 👑黑卡会员
发布于 2026-10-23 02:13 ·8 浏览 ·0 回复
内容摘要

说明用 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 秒,未上传头像的账号无法发帖。

本文转载自 GJ站长论坛,原文地址:https://www.gj0.com/thread-2400.html
转载请注明出处,版权归原作者所有。
—/ 5暂无评分
还没有评分,来打第一分吧

全部回复 0

还没有回复,来抢沙发~