Skip to content
本页目录

fastclick

fastclick 是一个早期为了解决移动端 click 事件 300ms 延迟问题的插件,不过现在已经不推荐使用了,但了解其发展历程与实现原理,可以有助于我们了解移动端的 touch 事件。

300ms 延迟的原因

它是 2007 年由 iphone 引入的,为了实现页面双击缩放效果(早期一般网站还没有做移动端适配,pc端网页在移动端打开会非常小)。当用户点击时,会等待 300ms ,监听此期间内是否会再次点击,触发 dbtap。若无再次点击才会触发类似 click 效果。后期移动端浏览器几乎都实现了这个效果。可以理解为: touchstart -> touchend -> click

关于点击穿透

一般是弹出层上绑定了点击事件,当用户点击关闭按钮收起来弹出层,但300ms后浏览器才会在点击位置触发click事件,此时弹出层已经隐藏,就会在下一层元素上触发,如果下一层刚好绑定了click事件或者是a链接,就会触发事件。

解决方案

当前最简单且无副作用的方案是 CSS3 的 touch-action: manipulation;

浏览器只允许进行滚动和持续缩放操作。任何其他被 auto 值支持的行为不被支持。启用平移和缩小缩放手势,但禁用其他非标准手势,例如双击以进行缩放。禁用双击可缩放功能可减少浏览器在用户点击屏幕时延迟生成点击事件的需要。这是“pan-x pan-y pinch-zoom”(为了兼容性本身仍然有效)的别名。

实现原理

监听 touchstarttouchend 事件,阻止默认的 click 事件(event.preventDefault()),合成自定义 click 事件并执行。

JS
let targetElement = null
document.body.addEventListener('touchstart', function () {
	targetElement = event.target // 记录点击元素,用于点击结束后在该元素上触发事件
})

document.body.addEventListener('touchend', function (event) {
	event.preventDefault()	// 阻止默认事件(屏蔽之后的click事件)

	let touch = event.changedTouches[0]

	// 自定义 click 事件,并添加可跟踪属性 forwardedTouchEvent
	let clickEvent = document.createEvent('MouseEvents')
	clickEvent.initMouseEvent('click', true, true, window, 1, touch.screenX, touch.screenY, touch.clientX, touch.clientY, false, false, false, false, 0, null)
	clickEvent.forwardedTouchEvent = true // 自定义的
	targetElement.dispatchEvent(clickEvent)
})
let targetElement = null
document.body.addEventListener('touchstart', function () {
	targetElement = event.target // 记录点击元素,用于点击结束后在该元素上触发事件
})

document.body.addEventListener('touchend', function (event) {
	event.preventDefault()	// 阻止默认事件(屏蔽之后的click事件)

	let touch = event.changedTouches[0]

	// 自定义 click 事件,并添加可跟踪属性 forwardedTouchEvent
	let clickEvent = document.createEvent('MouseEvents')
	clickEvent.initMouseEvent('click', true, true, window, 1, touch.screenX, touch.screenY, touch.clientX, touch.clientY, false, false, false, false, 0, null)
	clickEvent.forwardedTouchEvent = true // 自定义的
	targetElement.dispatchEvent(clickEvent)
})