133 lines
3.9 KiB
JavaScript
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() |