触摸事件的响应顺序
ontouchstart
ontouchmove
ontouchend
onclick
graph LR
ontouchstart-->ontouchmouve
ontouchmouve-->ontouchend
ontouchend-->onclick
现象
当A/B两个层上下z轴重叠,上层的A点击后消失或移开(这一点很重要),并且B元素本身有默认click
事件(如a标签)或绑定了click
事件。在这种情况下,点击A/B重叠的部分,就会出现点透的现象。
原因
是由于浏览器事件派发机制导致的,并非冒泡的原因。
zepto的tap
事件是通过兼听绑定在document
上的touch
事件来完成tap
事件的模拟的,并且tap
事件是冒泡到document
上触发的
在移动端不使用click
而用touch
事件代替触摸是因为click
事件有300ms延迟
由于我们在touchstart
阶段就已经隐藏了A,300ms后click
事件触发时,浏览器将click
事件派发到了B,导致了异常的发生。
解决方法:
1 使用fastClick
fastClick将touch
事件绑定到了body
元素或顶层元素,在touch
事件中标记手势的位置和时间,根据此信息拦截了300ms后的真正的click
事件
具体的源码分析参考这篇文章。
2 使用touchend
代替tap
对于B元素本身存在默认click
事件的情况,应用touchend
代替tap
事件并阻止A元素touchend
的默认行为preventDefault()
,从而阻止click
事件的产生。
$("#aa").on("touchend", function (event) {
//很多处理比如隐藏什么的
event.preventDefault();
});
由于PC端是不支持touchend
事件的,可以同时绑定touchend
和click
事件
$("#save_and_back").on("touchend", function(e) {
save_article(article_data).then(function(res) {
location.href = "home.html";
});
e.preventDefault();
});
$("#save_and_back").on("click", function(e) {
save_article(article_data).then(function(res) {
location.href = "home.html";
});
e.preventDefault();
});
原理是:
在PC端上,没有touchend
事件,只有click
事件被绑定上了。
在移动端上,绑定了touchend
和click
事件,但是touchend
事件优先级比click
高,并且阻止了事件继续冒泡。所以两个端上都能完美实现效果,具体还有没有其他的问题暂时不得而知。
3 延时执行
通过延时执行tap
的事件,错开click
被触发的时机
$("#aa").on("tap", function(event) {
setTimeout(function() {
//很多处理比如隐藏什么的
}, 320);
});