自定义事件需同时满足cancelable: true、监听方调用preventDefault()、触发方检查defaultPrevented,才能实现可取消行为。

在自定义事件中设置 cancelable: true,只是让事件具备“可取消”属性,真正实现被外部拦截并阻止默认行为,还需要配合 event.preventDefault() 的调用和合理的事件设计逻辑。
1. 创建可取消的自定义事件
使用 CustomEvent 构造函数时,必须显式传入 { cancelable: true } 选项,否则即使调用 preventDefault() 也无效(不会报错,但无效果):
const evt = new CustomEvent('myAction', { cancelable: true });- 如果漏掉
cancelable: true,evt.cancelable为false,evt.preventDefault()不会改变evt.defaultPrevented状态
2. 在事件监听器中主动调用 preventDefault()
只有监听方(外部代码)在响应事件时调用 event.preventDefault(),才能标记该事件“被阻止”。这一步完全由监听者决定,不自动发生:
element.addEventListener('myAction', (e) => { if (shouldBlock) e.preventDefault(); });- 之后可通过
e.defaultPrevented判断是否被拦截,决定是否继续执行后续逻辑
3. 触发后检查 defaultPrevented 再执行关键操作
事件派发后,**触发方**需检查 event.defaultPrevented,以此作为是否继续执行默认行为的依据。这是实现“被阻止”的关键闭环:
element.dispatchEvent(evt);if (!evt.defaultPrevented) { doActualWork(); }- 注意:
dispatchEvent()是同步的,所以检查必须紧跟其后;异步回调中无法再访问原事件对象的defaultPrevented
4. 实际应用示例:可拦截的表单提交前校验
比如封装一个组件,允许父级提前干预提交:
- 组件内:
const submitEvt = new CustomEvent('before-submit', { cancelable: true }); - 组件内:
if (!this.dispatchEvent(submitEvt)) return;(等价于!submitEvt.defaultPrevented) - 父级监听:
el.addEventListener('before-submit', e => { if (invalid) e.preventDefault(); });
不复杂但容易忽略:cancelable 是开关,preventDefault 是动作,defaultPrevented 是结果——三者缺一不可。

















