为什么onClick事件会触发两次?

问题描述 投票:0回答:13

我有以下 HTML 内容:

<span onclick="alert('Boem')">
    <button id="test1">test</button>
</span>

当我调用以下 JavaScript 代码时:

$('#test1').trigger('click');

onclick 事件被触发两次,而我希望它只触发一次。因为 jQuery 应该在 DOM 树中查找并只找到一个 onclick。

我无法控制跨度,它是在第三方工具中生成的。我确实可以控制按钮及其参数。

您可以在这里找到 JSFiddle 示例: http://jsfiddle.net/Voga/v4100zke/

我不知道span的onclick监听器的内容。这也是由第三方工具生成的。我希望点击触发器像现在一样执行这个 onclick,但只执行一次。

javascript jquery html
13个回答
40
投票

它调用了两次,因为按钮位于跨度内,并且跨度具有

onclick="alert('Boem')"
,因此当您触发单击按钮时,它会显示一个警报,并且相同的单击事件传播到跨度并再次显示警报。

您需要使用以下代码停止按钮的默认行为:

$(function(){
    $('#test1').click(function(e){e.preventDefault();}).click();
});

演示


36
投票

我也遇到了类似的问题,我必须下载一个 pdf 文件,但该文件被下载了两次。我使用了 jQuery 的 stopImmediatePropagation 方法。

$( "#test1" ).on("click", function(e) {
     e.stopImmediatePropagation();
});

$('#test1').trigger('click');

stopImmediatePropagation 将阻止任何父处理程序以及任何其他处理程序执行。请参阅此处了解更多详情。


13
投票

要停止事件传播,请使用: stopPropagation

$( "#test1" ).on( "click", function(ev) {
    ev.stopPropagation();
});

$('#test1').trigger('click');

请注意订单事件是在 DOM 中分配的。

演示


6
投票

冒泡。子级上的点击事件也会发生在父级(跨度)上。


1
投票

我在 Modal 上也面临这个问题

通过以下技巧解决 -

$('#saveButton').off('click').on('click', { modal: modal }, save)

这里

off('click')
可以防止 save 方法多次触发。


0
投票

这也应该有效:

$($('#test1').parent()).trigger('click');

0
投票

这里

button click is triggered
。由于
button
位于
span
内部,并且为
onclick
定义了
span
事件,因此发生了
two alert

One is by the button 

other by its parent
(父级有onclick事件并触发按钮点击)。

为了避免出现两个警报,请使用此功能

<span>
    <button onclick="alert('Boem')" id="test1">test</button>
</span>

0
投票

我也有同样的问题。 我的事实是,我使用的是

.trigger('.element')
并且该
element
类有两个元素。

因此,我变得更具体,并使用

.trigger('.parent .element')
来确保单个元素上只发生一次单击事件,而不是两个元素上发生一次单击事件。


0
投票

为什么onClick事件会触发两次?

这是由于冒泡而发生的。这是因为,正如 javascript.info 所说:“事件从内部元素向上通过父级“冒泡”,就像水中的气泡

如何解决?

如果您的第三方工具生成包含

<span></span>
属性的
onclick
元素,这可能意味着您的工具希望您直接将 span 视为按钮,而无需像您一样创建额外的按钮正在处理您的
<button></button>
元素。

在这里,要修复此错误,最好的方法是以编程方式单击包含处理程序的 same 元素以避免传播:

$('#test1').trigger('click');
/* Now, you can take #test1 and make it look and function as a button */

#test1 {
  padding: 10px 20px;
  color: white;
  background-color: #0078d7;
  font-size: 2rem;
  font-family: Helvetica;
}

#test1:hover {
  cursor: pointer;
  background-color: blue;
  transition: all 0.25s;
}
<!-- Script to include jQuery v3.3.1 -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<span id="test1" onclick="alert('Boem')">test</span>


0
投票

注意你使用了jQuery的click方法。它将发出 DOM's 鼠标单击事件和 jQuery 的单击事件。然后 jQuery 的单击事件和 DOM 的鼠标单击事件都会传播到 span 元素,并且它的 onclick 侦听器被触发两次,因此它会发出两次警报。

查看这个演示来弄清楚。

至于如何处理,只需像之前的答案一样使用stopPropagation即可。

$('#test1').click(function() {

  // comment this line and run, 'parent' will be alerted TWICE!!! since both mouseEvent and jQuery.Event trigger the onclick listener
  $('#children').click(function(e) {e.stopPropagation()})

});

0
投票

这个问题将有助于回答“为什么”。

更好的方法是为元素分配一个点击处理程序,以便将 JavaScript 代码从 HTML 中抽象出来:

http://jsfiddle.net/v4100zke/3/

$('#test1').click(function() {
    alert('Boem')
});

0
投票

就我而言,没有嵌套按钮,但我遇到了同样的问题。我解决了添加“return false;”的问题活动结束时。

$('#test1').click(function() {
    alert('Boem');
    return false;
});

0
投票

在我的例子中,我在父 div 上添加事件监听器来触发点击事件。在此事件侦听器中,我需要触发隐藏输入上的单击事件。所以第二次点击呼叫第一个,我接到了两个电话。为了避免这种行为,我在输入上添加了事件侦听器以停止传播事件。

item.addEventListener('click', (event) => {

      event.stopPropagation();
      event.preventDefault();

      var checkbox = item.querySelector('input[type="checkbox"]');
      if (checkbox) {

        checkbox.click();
        item.classList.toggle('is-selected');
      }
    });

    item.querySelector('input').addEventListener('click', function (event) {

      // Avoid that the click on checkbox trigger parent event.
      event.stopPropagation();
    })
  });
© www.soinside.com 2019 - 2024. All rights reserved.