如果您切换位于上方的元素的高度,则触摸设备上有关于链接的可点击区域的奇怪行为。如果您运行以下代码段(例如,在本地保存并使用chrome来模拟触摸事件),您会注意到在某些情况下您没有点击红色链接区域时,哈希#mylink
会添加到网址中。有时你点击红色区域,它不会被添加。
E.g。
#mylink
添加到网址,就像您单击了红色链接区域一样。 =>为什么?#mylink
不会添加到网址中。 =>为什么?#mylink
不会添加到网址中。 =>为什么?
<html>
<head>
<style type="text/css">
.test {
background: grey;
height: 200px;
}
.test.is-visible {
height: 400px;
}
.link {
height: 600px;
display: block;
background: red;
}
</style>
<script type="text/javascript">
(function() {
window.addEventListener( 'touchstart' , function() {
document.getElementsByClassName("test")[0].classList.toggle('is-visible');
});
})();
</script>
</head>
<body>
<div class="test">
Click the grey area. Element enhances and minimizes itself. Now click on the lower half of the enhanced grey area (if grey = enhanced) or on the white area up to 200px below of the red area (if grey = minimized). #mylink is added to the url as if you had clicked on the red area. Why?
</div>
<a href="#mylink" class="link">The red area is the "normal" click area.</a>
</body>
</html>
我在iOS和Android上尝试了这一功能,并在Chrome和Firefox中模拟了触控事件。他们都表现得一样。
如果我收听click
而不是touchstart
或touchend
事件,则会按预期运行。
造成这种差异的原因是什么?如果我听触摸事件而不是点击事件,为什么链接区域不同/错位?
答案 0 :(得分:4)
当您增强灰色区域并触摸下半部分时会发生这种情况:
touchstart
事件is-visible
类
200px
touchend
事件,这是确定链接是否被触及的事件点击红色元素下面的区域200px
时会发生同样的事情:
touchstart
事件is-visible
类
200px
touchend
事件,这是确定链接是否被触及的事件答案 1 :(得分:2)
<强> TL; DR 强>
浏览器在touchend
位置触摸事件后执行点击事件,无论内容是否因为分配给触摸事件的功能而发生变化。
在挖掘Touch Events specification后,我想我可以回答我的问题:
Section 8描述了触摸事件与鼠标事件的交互并单击。它说:
用户代理可以调度触摸事件和(...)鼠标事件以响应相同的用户输入。
和
如果用户代理将一系列触摸事件解释为点击手势,那么它应该在touchend事件的位置发送mousemove,mousedown,mouseup和click事件(按此顺序) 用于相应的触摸输入。
如果在处理触摸事件期间文档的内容具有改变,则用户代理可以将鼠标事件分派给与触摸事件不同的不同的目标。
最重要的
元素的激活(例如,在某些实现中,点击)通常会产生以下事件序列(尽管这可能略有不同,具体取决于特定的用户代理行为):
1。) touchstart
2。)零个或多个touchmove事件,取决于手指的移动
3。) touchend
4。)mousemove(与旧版鼠标特定代码兼容)
5.。mousedown
6。)mouseup
7。)点击
因此,总结上面的例子,这意味着:
1。)touchstart
或touchend
被触发。
2。)首先处理自定义函数,切换类并更改元素的高度/位置。
3.)之后,click
事件在touch
事件发生的同一点执行,但现在涵盖了不同的目标。
规范也提供了一种防止这种情况的方法:
如果取消touchstart,touchmove或touchend,则用户代理不应发送任何因阻止触摸事件而导致的鼠标事件。
所以我想“修复”这种行为的最简单方法是使用`preventDefault()'来阻止事件,然后手动点击事件的目标并最后切换类:
window.addEventListener( 'touchstart' , function(event) {
event.preventDefault();
event.target.click();
document.getElementsByClassName("test")[0].classList.toggle('is-visible');
});
Chromium bug追踪器中有一个statement,证明了这一点。