CustomEvent 必须用 detail 字段传数据,其他字段被忽略;不 new 实例就 dispatch 会报 TypeError;detail 为 null 安全,结构化对象推荐;避免传 DOM 节点或函数;dispatchEvent 需 Event 实例;需 bubbles: true 才冒泡;目标须已挂载;监听须从 e.detail 取值;事件名大小写敏感;detail 是引用传递。

必须用 detail 字段传数据,其他字段(如 data、payload)浏览器直接忽略;不 new 实例就 dispatch 会报 TypeError: parameter 1 is not of type 'Event'。
CustomEvent 构造函数必须显式传 detail 对象
浏览器只认 detail 这个 key,哪怕你写成 { data: { id: 1 } } 或 { payload: {} },监听端拿到的 event.detail 仍是 undefined。
-
new CustomEvent('user-login')→event.detail是undefined,不是空对象 -
new CustomEvent('user-login', { detail: null })→ 安全,明确表示“无有效数据” -
new CustomEvent('user-login', { detail: { userId: 123, token: 'abc' } })→ 推荐,结构清晰可读 - 避免在
detail中传document.getElementById('x')或函数,跨 iframe 或调试时可能触发DataCloneError
dispatchEvent() 必须作用于 EventTarget 实例,不能传字符串
常见错误是把事件名当参数直接传给 dispatchEvent,比如 el.dispatchEvent('user-login') —— 这会立刻报错,因为浏览器要求第一个参数必须是 Event 实例。
- 正确路径:先
const evt = new CustomEvent(...),再el.dispatchEvent(evt) - 目标可以是
document、window、任意HTMLElement,甚至自定义类(只要继承EventTarget) - 若想让父级监听到,构造时必须设
bubbles: true;否则事件只在目标节点触发,不冒泡 - 目标元素必须已挂载到 DOM,否则 dispatch 静默失败(不报错,但监听器收不到)
监听时必须从 event.detail 安全取值,不能解构顶层 event
监听回调里的 event 是 CustomEvent 实例,它有 type、target 等原生属性,但业务数据只在 event.detail 下。直接 const { userId } = event 会得到 undefined。
立即学习“前端免费学习笔记(深入)”;
- 基础写法:
document.addEventListener('user-login', e => console.log(e.detail.userId)) - 防御性写法:
const data = e.detail ?? {}; console.log(data.userId || 'missing') - 现代环境可用可选链:
e.detail?.userId - 事件名大小写敏感,
'User-Login'和'user-login'是两个不同事件
最易被忽略的是:detail 值是引用传递,不是深拷贝。如果派发后还继续修改原始对象,监听方看到的可能是已被覆盖的状态——需要隔离时得手动 structuredClone() 或序列化再解析。


















