1. 背景
最近项目上有需要在移动端监听onTap
和onLongTap
的需求,然后自己摸索了一下,实现了一个自定义事件监听,源码如下
2. 源码
;(function() {
// 默认长按多久之后触发 onTap 和 onLongTap
let DURATION = 300
/**
* 初始化事件监听
* @example
* initEvent({ duration: 300 })
*/
function initEvent(options) {
if (!isNaN(options.duration) && options.duration > 0) {
DURATION = options.duration
}
for (let node of document.body.childNodes) {
if (node.nodeType === 1) bindTapEvent(node)
}
}
/**
* 绑定 onTap 和 onLongTap 事件,默认 300ms 之前是点击;之后是长按
* @param {HTMLElement} node
*/
function bindTapEvent(node) {
const ON_TAP_NAME = 'tap'
const ON_LONG_TAP_NAME = 'longtap'
// 找到 onTap
const onTap = node.getAttribute(`on${ON_TAP_NAME}`)
// 找到 onLongTap
const onLongTap = node.getAttribute(`on${ON_LONG_TAP_NAME}`)
// 创建 touchstart 和 touchend 监听
node.addEventListener(
'touchstart',
e => {
this.startTouchTime = Date.now()
},
false
)
node.addEventListener(
'touchend',
e => {
this.endTouchTime = Date.now()
const diff = this.endTouchTime - this.startTouchTime
if (diff <= DURATION) {
createCustomEventAndEmit(ON_TAP_NAME, node)
if (onTap) eval(onTap)
} else {
createCustomEventAndEmit(ON_LONG_TAP_NAME, node)
if (onLongTap) eval(onLongTap)
}
},
false
)
}
/**
* 创建自定义事件,并触发该事件
* @param {String} eventName - 自定义事件名称
* @param {HTMLDivElement} element - 元素节点
* @returns {void}
*/
function createCustomEventAndEmit(eventName, element) {
const event = document.createEvent('Event')
event.initEvent(eventName, false, false)
element.dispatchEvent(event)
}
window.initEvent = initEvent
return { initEvent }
})()
3. 使用方法
<button id='btn'>点我试试</button>
<script>
// 1. 引入上面的源码,可以放到一个单独的js中
// 2. 执行事件初始化
initEvent({ duration: 300 })
// 3.1 给要实现的元素添加 tap 的事件监听
document.getElementById('tap', e => {
console.log('监听到 tap 事件', e)
}, false)
// 3.2 也可以给元素添加 `ontap='alert(123213)'`
</script>