按钮 onclick 函数触发两次

54

我有一个按钮,它使用事件处理程序调用JavaScript函数。由于某种原因,事件处理程序被调用了两次。

这是我的按钮(我使用PHP对象生成代码,因此有很多空标签):

<button name="addToCart" value="" size="" onclick="" src="" class="addToCartButton" id="0011110421111" type="button" formtarget="_self" formmethod="post" formaction="" data-mini="true" width="" height="" placeholder="" data-mini="1" onkeypress="" >Add To Cart</button>

这是我的事件处理程序:

$('.addToCartButton').click(function() {
    alert("bob");
    //addToCart($(this).attr("id"));
});

在这里,我得到了两次警告。

我尝试在按钮的onclick属性中调用addToCart函数,但是如果我这样尝试,我会收到以下错误:

TypeError: '[object HTMLButtonElement]' is not a function (evaluating 'addToCart(0011110421111)')

我也尝试了event.preventDefault()和event.stopPropagation(),但均无效。

有什么想法为什么会发生这种情况,或者我该如何防止其重复执行,或者如果我从onclick中调用javascript函数时为什么会出现错误?


3
你可能正在调用分配事件的那段代码两次! - epascarello
你为什么有这么多空白属性? - tymeJV
你是否在其他地方有一个onsubmit函数? - David Nguyen
1
$._data($(".addToCartButton")[0],"events").length 告诉你什么?它应该返回绑定到该按钮的事件数量。 - matewka
9
我的错误。请按照以下方式操作:打开Chrome浏览器,进入您的网站,按F12,点击“控制台”选项卡,然后粘贴此代码:“$._data( $(".addToCartButton")[0], "events")”。将打印包含绑定到按钮的所有事件的对象到控制台。 click属性应该是一个具有多个元素的数组。展开它们中的每一个,并右键单击处理函数。选择“显示函数定义”,您应该可以看到在您的代码中定义每个处理程序的位置。这样您应该能够找到重复的处理程序。 - matewka
显示剩余5条评论
10个回答

113

可能您正在同一个按钮上两次附加事件。您可以像这样取消绑定以前设置的任何点击事件:

$('.addToCartButton').unbind('click').click(function() {
    alert("bob");
    //addToCart($(this).attr("id"));
});

这适用于所有附加的事件(mouseover,mouseout,click等)


8
.off().on() 可能更流行。 - mplungjan
27
既然这个答案可能有效,我就不会对它进行“-1”评分。但我强烈反对通过“撤销”而非找到真正的问题并将其删除来修复事物。 - matewka
@matewka:感谢您的建议,非常有价值。它让我避免了破坏我的代码。在我看来,这个答案不应该被评为-1,因为它指出了一个不太明显的问题,即许多人可能会在同一对象上设置两次事件监听器。 - Giampaolo Ferradini

15

我的事件触发了两次,因为我错误地同时包含了my_scripts.js和my_scripts.min.js。请确保只包含一个。


8

从选择器中解除事件绑定,在将其重新添加到DOM元素后,再次在特定的选择器上触发事件。

$("selector_name").unbind( "event" ); // 执行此调用后,再次在选择器上触发事件。
$( "#button" ).unbind( "click" );

$("#button").click(function(event) {
console.log("button click again);
});

8

仅供记录,以防其他人遇到同样的问题,我也遇到了相同的问题,根本原因是有3个带有相同ID的按钮,在点击其中一个之后,另外两个也触发了它们的OnClick事件...


3

你可能想传入事件并添加:

$('.addToCartButton').click(function(e) {
  e.preventDefault(); //Added this
  alert("bob");
  //addToCart($(this).attr("id"));
});

或者

$('.addToCartButton').click(function(e) {
  e.preventDefault(); //Added this
  alert("bob");
  //addToCart($(this).attr("id"));
  return false;
});

OP说这没有帮助。 - matewka
OP说了preventDefault,但他没有提到返回false。 - bosspj
1
无论如何,preventDefault不是一个属性,而是一个函数。 - matewka

2

对我来说,我发现我的事件没有绑定到我的映射组件上。相关的答案在为什么我的 onClick 在渲染时被调用?- React.js,但是为了提供一些见解,我复制了一些答案(希望这有所帮助!):

1. 使用 .bind

activatePlaylist.bind(this, playlist.playlist_id)

2. 使用箭头函数

onClick={ () => this.activatePlaylist(playlist.playlist_id) }

3. or return function from activatePlaylist

activatePlaylist(playlistId) {
  return function () {
     // you code 
  }
}

1

我在我的MVC项目中遇到了同样的问题,问题出在我两次引用了site.js;一次在_Layout.cshtml文件中,一次在主cshtml文件的Scripts部分。移除其中一个就解决了这个问题。


0

我来到这里寻找答案。结果发现我的问题不完全是触发两次,而是当我稍后点击其他东西时,它也会为该点击触发。

我有一个带有点击监听器的容器 div。 在该 div 内部,有一个可点击的链接。

点击链接也会触发容器的点击事件。

我花了一些时间进行 unbind('click') / rebind 实验,但没有什么令人满意的结果。最终,我只是在容器的 click 事件中放置了一个条件,以便仅在点击目标不是锚点时才运行它: -

    if (e.target.tagName !== 'A') {    
        alert("bob");
        //addToCart($(this).attr("id"));
    });

0

对于这种类型的错误:

  • 可能是因为您绑定了重复的事件
  • 要么事件处理程序被连接了两次,要么可能在预期的侦听器完成侦听并完成其工作后,事件没有被解除绑定。

在这种情况下,当您不再需要侦听时,您需要做一些事情来解除绑定侦听器。


-1

我的错误是让父元素和我附加点击事件处理程序的子元素具有相同的类名,这给我带来了一些困惑。


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