防止触发文档事件监听器?

时间:2019-04-02 11:23:28

标签: javascript

我有document.addEventListener('touchstart', this.onDocument);,因此我可以检测到用户何时单击某些内容。

但是在我的按钮单击处理程序上,我有:

toggleItemActive(e) {
        e.stopPropagation();
        ....

但是当我单击iPad上的按钮时,文档触摸处理程序仍然运行。

如何在不运行文档触摸处理程序的情况下允许单击按钮?

3 个答案:

答案 0 :(得分:1)

您可以使用Event#preventDefault,但如果需要,还需要检查容器中的Event#defaultPrevented标志。

使用Event#defaultPrevented的示例

document.addEventListener("click", function(event) {
  if (event.defaultPrevented) return;
  console.log("Container Clicked");
});
document.querySelector("#test").addEventListener("click", function(event) {
  event.preventDefault();
  console.log("Test Clicked");
});
<button id="test">Test</button>

不带Event#defaultPrevented的示例

document.addEventListener("click", function(event) {
  console.log("Container Clicked");
});
document.querySelector("#test").addEventListener("click", function(event) {
  event.preventDefault();
  console.log("Test Clicked");
});
<button id="test">Test</button>

使用Event#defaultPreventedtouchstart事件)的示例

document.addEventListener("touchstart", function(event) {
  if (event.defaultPrevented) return;
  console.log("Container Clicked");
});
document.querySelector("#test").addEventListener("touchstart", function(event) {
  event.preventDefault();
  console.log("Test Clicked");
});

var event = document.createEvent("HTMLEvents");
event.initEvent("touchstart", true, true);
document.querySelector("#test").dispatchEvent(event);
<button id="test">Test</button>

同时使用clicktouchstart侦听器的示例

document.addEventListener("touchstart", function(event) {
  if (event.defaultPrevented) return;
  console.log("Container Clicked");
});
document.querySelector("#test").addEventListener("touchstart", function(event) {
  event.preventDefault();
});
document.querySelector("#test").addEventListener("click", function(event) {
  console.log("Test Clicked");
});
<button id="test">Test</button>

使用忽略数组的示例

var excludedList = ["test"];

document.addEventListener("touchstart", function(event) {
  if (excludedList.indexOf(event.target.id) !== -1) return;
  console.log("Container Clicked");
});
document.querySelector("#test").addEventListener("click", function(event) {
  console.log("Test Clicked");
});

var event = document.createEvent("HTMLEvents");
event.initEvent("touchstart", true, true);
document.querySelector("#test").dispatchEvent(event);
<button id="test">Test</button>

答案 1 :(得分:0)

this.onDocument处理程序中,检查event.currentTarget是否是您要防止的按钮,并且什么也不做。 这样的事情应该可以工作

onDocument(e){
  // get access to the target button e.g assuming your button has an id targetButton
  let targetButton = document.querySelector('#targetButton')

  // do no thing if the target button is clicked
  if(e.currentTarget === targetButton){
    return;
  }

  // do whatever you want to do
}

答案 2 :(得分:0)

问题是touchstartclick之前触发,因此您永远无法事先知道触摸是否会分解为点击(它将始终触发)。

“解决”问题的最简单方法是在touchStart事件处理程序中检查要处理的内容。

function onDocumentTouchStart(e){
  if (!e.target.matches('button|a.this-one')) { // refine queryString for exclusions
    // proceed with logging
  }
}

或在单击按钮时短暂分离touchstart事件处理程序。这行得通,但是由于它使用了异步重新连接,因此感觉有点脏。

const onDocumentTouchStart = ()=>console.log('touchstart')

toggleDocumentTouchStart(true)

const button = document.querySelector('button')
button.addEventListener('touchstart', e => {
  toggleDocumentTouchStart(false)
	requestAnimationFrame(toggleDocumentTouchStart.bind(null,true))
})
button.addEventListener('click', ()=>console.log('buttonClick'))

function toggleDocumentTouchStart(add){
	add
		?document.body.addEventListener('touchstart', onDocumentTouchStart)
		:document.body.removeEventListener('touchstart', onDocumentTouchStart)
}
<button>button that prevents</button>
<div>foo</div>
<button>another button</button>