/** * Uniapp DOM 事件桥接类,用于将 DOM 事件桥接到 EventBus * 支持将 DOM 事件转换为 EventBus 事件,可配置是否阻止默认行为和停止传播 * * @author ZFSun * @version 1.0.0 * @createTime 2023-08-10 */ class DomEventBridge { constructor() { this.eventBus = null this.domListeners = new Map() } // 设置 EventBus 实例 setEventBus(eventBus) { this.eventBus = eventBus } // 桥接 DOM 事件到 EventBus bridgeDomEvent(domEventName, eventBusEventName, options = {}) { const handler = (domEvent) => { if (!this.eventBus) return // 创建 EventBus 兼容的事件对象 const eventBusEvent = this.createEventBusEvent(domEvent, eventBusEventName) // 触发 EventBus 事件 const shouldContinue = this.eventBus.emit(eventBusEventName, eventBusEvent) // 根据 EventBus 处理结果决定是否阻止 DOM 事件默认行为 if (!shouldContinue && options.preventDefault) { domEvent.preventDefault() } // 根据 EventBus 处理结果决定是否停止 DOM 事件传播 if (!shouldContinue && options.stopPropagation) { domEvent.stopPropagation() } } // 保存监听器引用以便清理 const listenerKey = `${domEventName}-${eventBusEventName}` this.domListeners.set(listenerKey, handler) // 添加 DOM 事件监听 // #ifdef H5 document.addEventListener(domEventName, handler, options) // #endif return () => this.unbridgeDomEvent(domEventName, eventBusEventName) } // 创建 EventBus 兼容的事件对象 createEventBusEvent(domEvent, eventBusEventName) { return { type: eventBusEventName, domEvent: domEvent, originalEvent: domEvent, target: domEvent.target, currentTarget: domEvent.currentTarget, timestamp: Date.now(), // EventBus 的取消方法 preventDefault: function () { this._preventDefault = true }, stopPropagation: function () { this._stopPropagation = true }, // DOM 事件的代理方法 stopImmediatePropagation: function () { domEvent.stopImmediatePropagation() }, get isDefaultPrevented() { return this._preventDefault || false }, get isPropagationStopped() { return this._stopPropagation || false } } } // 取消桥接 unbridgeDomEvent(domEventName, eventBusEventName) { const listenerKey = `${domEventName}-${eventBusEventName}` const handler = this.domListeners.get(listenerKey) if (handler) { // #ifdef H5 document.removeEventListener(domEventName, handler) // #endif this.domListeners.delete(listenerKey) } } // 从 EventBus 触发 DOM 事件 triggerDomEventFromEventBus(domEventName, detail = {}) { // #ifdef H5 const event = new CustomEvent(domEventName, { bubbles: true, cancelable: true, detail: detail }) document.dispatchEvent(event) return !event.defaultPrevented // #endif // #ifdef MP // 小程序环境不支持 DOM 事件 return true // #endif } // 清理所有桥接 destroy() { for (const [listenerKey, handler] of this.domListeners) { const [domEventName] = listenerKey.split('-') // #ifdef H5 document.removeEventListener(domEventName, handler) // #endif } this.domListeners.clear() } } export default new DomEventBridge()