Hammer.js在tap动作后触发了位于被点击元素后面的DOM元素的click事件。

7
我使用Hammer.js在移动设备上检测触摸事件,如轻敲、滑动等。
我有一个交互,在轻敲时,我隐藏被点击的内容(以及可能的父级),并在其位置显示其他内容(类似于更改屏幕功能)。
问题是,新显示的内容可能已经绑定了自己的事件,或者本地化地在轻敲时进行交互(例如标签切换复选框,文本输入聚焦)。如果组件在轻敲发生时立即隐藏/显示,则400ms的单击事件仍在运行,并且随后会触发下面的元素。
在移动设备上查看此jsfiddle:

http://jsfiddle.net/annam/xGJZL/

http://jsfiddle.net/annam/xGJZL/embedded/result/

<div class="checkbox">
    <input type="checkbox" id="check" />
    <label for="check"></label>
</div>
<div class="box"></div>

<style>
.checkbox { width: 500px; height: 500px; position: absolute; top: 0; ; left: 0;  }
.checkbox input { display: none; }
.checkbox label { display: block; width: 100%; height: 100%; background: yellow; }
.checkbox input:checked + label { background: green; }
.box { position: absolute; top: 0; left: 0; width: 200px; height: 200px; background: pink; }
</style>

<script>
$('.box').hammer().on('tap', function(e){ $(this).hide(); })
$('label').hammer().on('tap', function(e){ $('.box').show(); })
</script>

请查看下方标签如何在触摸屏上被切换(仅限移动设备!)。这在网页上不会发生,因为标签可见并且在触摸开始事件后的400ms内触发了本机点击事件。

还可以尝试将标签上的触摸事件更改为本机点击事件。这也会错误地触发(仅限移动设备!)。

我注意到除了单击事件和标签之外,其他情况也会发生,例如输入字段,在显示在触摸事件后立即聚焦文本输入字段(并弹出键盘)。

使用preventDefault和stopPropagation无法解决此问题,因为它不是事件冒泡的问题,而且被阻止的事件实际上是“tap”,而我们需要停止的是在click/mousedown/touch范围内的某些东西。这似乎在hammerjs v1和v2中都会发生(v1使用e.gesture.preventDefault()等也无效)。

有没有办法避免这种情况?

1个回答

8

在Hammer.js的创建者Jorik的反馈后,这里提供了两种不同的解决方案:

解决方案1

clickbuster.js,它会在触摸结束事件后,在给定时间内阻止在相同位置发生的点击事件的默认行为和事件传播。这似乎非常适用于防止绑定的点击事件和防止标签切换复选框,但无法防止输入框获取焦点。适用于Hammer v1和v2,只需嵌入脚本即可处理所有其余内容。

解决方案2

e.gesture.srcEvent.preventDefault()

在本机touchstart事件上使用preventDefault。这似乎更加可靠,也适用于输入焦点问题。但只适用于hammer v2。需要在所有.on('tap')绑定内调用。


第二个解决方案完美地解决了问题。我没有尝试第一个解决方案。 - Dilhan Jayathilake
仅仅嵌入PreventGhostClick.js并不能处理所有其他问题,你必须定义要防止鬼点击的元素(如注释中所写)。使用 PreventGhostClick(myElement); 来防止鬼点击。同时注释中也写到了不建议使用 PreventGhostClick(document); 。因此,你的第二个解决方案对我来说是可行的。 - woheras
1
我的建议是:删除或注释掉第一个解决方案。第二个方案太简单而且优雅了。没有人再使用v1了。 - tao

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接