在另一个点击事件之后添加点击事件

14

我尝试将一个点击事件添加到通过按钮附加的另一个点击事件中的文档上。然而,第二个点击事件会立即触发,就好像事件重叠了一样。我尝试过阻止传播、使用超时、移除侦听器和preventDefault(),但都没有成功。

这是我要做的事情的一个示例。

document.getElementById("test").addEventListener('click', first);

function first(){
    document.addEventListener('click', second);
}
function second(){
    alert("I'm not suppose to appear after the first click, only the second.");
}

进行测试时,我正在使用一个简单的按钮

<button type="button" id="test">Click</button>

我没有使用 JQuery。这是否可能?


你应该将第二个事件监听器附加到同一个“test”元素上吗? - Olivier De Meulder
1
Olivier,我想做的需要附加到整个文档中,无论您在哪里单击,它都会触发下一个事件。Hanlet,标记已发布,非常简单 :) - Alexander Weihmayer
我收到的答案似乎有效,但是否有人能够解释一下发生了什么,以及为什么第二个事件会立即触发?我很快就会接受一个答案,只是想等待看看是否还有其他信息!谢谢大家 - Alexander Weihmayer
1
这是由于事件冒泡造成的:https://dev59.com/4W445IYBdhLWcg3w9Oss(事件被转发到上一级),因此会发生以下情况:1)按钮上的点击事件;2)您将一个事件监听器附加到body;3)点击事件被转发到body(现在具有事件监听器)。 - valepu
1
我的天啊,我怎么这么无知。这是一条有价值的信息,我不知道什么是冒泡。非常感谢! - Alexander Weihmayer
显示剩余2条评论
2个回答

18
尝试使用 event.stopImmediatePropagation()

document.getElementById("test").addEventListener('click', first);

function first(e){
    e.stopImmediatePropagation();
    this.removeEventListener("click", first);
    document.onclick = second;
}
function second(){
    alert("I'm not suppose to appear after the first click, only the second.");
}
<button type="button" id="test">Click</button>


啊,我不知道还有另一种阻止传播的事件。这看起来像是我期望的答案。不过,在接受之前,我会再等一段时间,看看是否还有其他情况出现。谢谢! - Alexander Weihmayer
@AlexanderWeihmayer 看更新的帖子;包括使用 .one() 的 jQuery 方法。 - guest271314
不错的补充。JQuery确实让生活更轻松,但DIY总是有一些酷炫的东西 :) - Alexander Weihmayer
@AlexanderWeihmayer 更新了纯js解决方案;现在在第二次点击#test时调用second函数。 - guest271314
谢谢,您给出的答案似乎非常直接和高效,我会接受它。 - Alexander Weihmayer
有没有办法在第三次点击时取消? - Fernando B

2
您可以使用一个变量来记录点击次数。
document.getElementById("test").addEventListener('click', clickHandler);

var clickCount=0;
function clickHandler(event){
  clickCount++;
  if(clickCount==2){
    event.target.removeEventListener("click");
    document.addEventListener('click', function(){
      alert("I'm not suppose to appear after the first click, only the second.");
    });
  }
}

如果您不想使用全局变量,可以使用数据集(dataset),并创建一个带有以下内容的按钮:

<button type="button" id="test" data-clickcount="0">Click</button>

使用以下代码:

document.getElementById("test").addEventListener('click', clickHandler);

function clickHandler(event){
  event.target.dataset.clickcount++;
  if(event.target.dataset.clickcount==2){
    event.target.removeEventListener("click");
    document.addEventListener('click', function(){
      alert("I'm not suppose to appear after the first click, only the second.");
    });
  }
}

1
@valepu 你也可以使用一个函数属性:clickHandler.clickcount. - Vidul
哦,还有更多我不知道的东西。谢谢 :) 但是,这种设置方式只会在按钮本身上触发,而我希望第二次点击可以在整个文档上触发。 - Alexander Weihmayer
我的错,没有注意到事件监听器的目标,但我可以解决这个问题。 - valepu
1
谢谢你提供的解决方案,但是guest271314的方法非常直接。不过我一定会记住这些技巧,感谢你给我的信息 :) - Alexander Weihmayer
1
没问题!我不会质疑品味,只是很高兴能帮到你。只需注意 stopimmediatepropagation,因为它可能会中断上层的其他点击事件(由于事件冒泡),所以如果您将按钮放在内部,比如一个带有另一个事件处理程序的<div>中,它就不会触发。 - valepu

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