重读 fastclick 源码
Talk is cheap, show me the code
最近遇到一点fastclick的报错,追踪下去,发现对于fastclick的源码其实并没有很好地理解清楚,找了些资料,决定重新读一遍。
起因
移动端click事件有300ms延迟
300ms延迟的原因: 移动端有一个双击缩放功能,浏览器需要判断用户点击是否为双击缩放
导致的结果:
- 用户体验差,很不流畅,尤其是在密集操作场景下,比如计算器等操作时,感觉反应很慢
- 会有点击穿透问题
看个例子:
|
|
可以看到按钮点击后,输出 touch end 88ms click 301ms
每次点击结果可能不同,但是不影响结论,就是click会延迟300ms执行
移动端Event事件顺序
- touchstart
- touchmove
- touchend
- mouseover — 当指针设备移动到存在监听器的元素或其子元素的时候,mouseover事件就会被触发
- mouseenter — 当指针设备( 通常指鼠标 )在元素上移动时, mousemove 事件被触发
- mousedown
- click
然而click存在300ms延迟,touch却是没有的
fastclick解析
思路
利用touch模拟tap点击,如果认为是一次有效的tap,则在touchend时立即模拟一个click事件,分发到事件源(相当于主动触发一次click),同时阻止掉浏览器300ms后产生的click。
源码
- 先看下结构
|
|
- fastclick的使用:
|
|
可见attach方法其实就是执行了fastclick的构造函数初始化
- 初始化
|
|
- 接下来是关键步骤
- touchstart,touchend是如何判断tap是否有效
- 模拟click事件
- 阻止300ms后的click
onTouchStart
|
|
onTouchMove
|
|
onTouchEnd
|
|
sendClick
|
|
onClick
在layer的click捕获阶段监听
|
|
总结
以上就是fastclick的源码解析
preventDefault/stopPropagation/stopImmediatePropagation
这里面涉及到这么几个阻止冒泡的方法,有什么区别呢。
MDN Summaries:
- Event.preventDefault()
Cancels the event if it is cancelable, without stopping further propagation of the event.
如果当前event.cancelable属性为true,则取消的当前事件的默认动作,但不阻止当前事件的进一步传播
The preventDefault() method tells the user agent that if the event does not get explicitly handled, its default action should not be taken as it normally would be. The event continues to propagate as usual, unless one of its event listeners calls stopPropagation() or stopImmediatePropagation(), either of which terminates propagation at once.
- Event.stopPropagation()
阻止当前冒泡或捕获阶段的进一步传播
The stopPropagation() method of the Event interface prevents further propagation of the current event in the capturing and bubbling phases.
- Event.stopImmediatePropagation()
阻止调用相同事件的其他监听器
The stopImmediatePropagation() method of the Event interface prevents other listeners of the same event from being called.
If several listeners are attached to the same element for the same event type, they are called in the order in which they were added. If stopImmediatePropagation() is invoked during one such call, no remaining listeners will be called.
createEvent
MDN Summary:
Creates an event of the type specified. The returned object should be first initialized and can then be passed to EventTarget.dispatchEvent.
创建一种类型的事件,返回一个对象,同时这个对象可以被传入dispatchEvent中进行分发。
type is a string that represents the type of event to be created. Possible event types include “UIEvents”, “MouseEvents”, “MutationEvents”, and “HTMLEvents”. See Notes section for details.
一共有四种模拟事件类型
- UIEvents
- MouseEvents
- MutationEvents
- HTMLEvents
|
|