Files
lucky_shop/common/js/dom-event-bridge.js
2025-10-30 18:23:35 +08:00

133 lines
3.9 KiB
JavaScript

/**
* Uniapp DOM 事件桥接类,用于将 DOM 事件桥接到 EventBus
* 支持将 DOM 事件转换为 EventBus 事件,可配置是否阻止默认行为和停止传播
*
* @author ZFSun <lauer3912@gmail.com>
* @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()