如何在Node 16的EventTarget中发送CustomEvent并实现浏览器端效果?
Node 16 环境 CustomEvent 实现
Node 16 内置Event和EventTarget但缺少CustomEvent实现,可直接通过继承Event实现完全对齐浏览器规范的CustomEvent,自动支持detail属性:
// 全局挂载CustomEvent,仅在不存在时定义避免覆盖浏览器原生实现 if (typeof globalThis.CustomEvent === 'undefined') { globalThis.CustomEvent = class CustomEvent extends Event { constructor(type, options = {}) { super(type, options); // 遵循浏览器规范,detail默认值为null this.detail = options.detail ?? null; } } }
实现后可以和浏览器端完全一致的方式调用:const myEvent = new CustomEvent('user:update', { detail: { id: 1, name: '张三' }, bubbles: true })
跨端 Event 扩展 data 属性方案
不建议直接修改原生Event的原型对象,避免全局原型污染引发的未知问题,优先选择封装兼容层实现两端统一:
/** * 跨端通用事件创建方法 * @param {string} type 事件类型 * @param {any} data 挂载到事件上的数据 * @param {Object} options Event初始化参数 * @returns {Event|CustomEvent} 兼容两端的事件实例 */ function createEvent(type, data = null, options = {}) { const event = typeof CustomEvent !== 'undefined' ? new CustomEvent(type, options) : new Event(type, options); // 统一挂载data属性 event.data = data; // 同步到detail属性,兼容原有业务逻辑 if (data != null && !event.detail) { event.detail = data; } return event; }
调用方式在Node和浏览器端完全一致,实例同时支持data和detail两个属性取值:const submitEvent = createEvent('form:submit', { formId: 123 }, { cancelable: true })
如果必须全局扩展Event的data属性,可通过以下方式实现,但存在和未来官方标准冲突的风险:
if (!('data' in Event.prototype)) { Object.defineProperty(Event.prototype, 'data', { value: null, writable: true, configurable: true, enumerable: true }); }
内容的提问来源于stack exchange,提问作者David Alsh
相关产品推荐
相关产品推荐

