【问题标题】:jQuery click event handler is called twice for a checkboxjQuery click 事件处理程序为复选框调用了两次
【发布时间】:2010-12-04 22:22:54
【问题描述】:

我对 ASPX 页面中的以下代码有疑问:

<script type="text/javascript">
$(document).ready(function() {
    $('.test').click(function() {
        alert("click")
    })
});
</script>

<asp:CheckBox runat="server" Text="Checkbox XYZ" CssClass="test" ID="cb1" />

在浏览器(FF3.5 / IE8)我有以下问题:

  • 如果我点击复选框(小方块),它会按预期工作
  • 如果我单击复选框的文本(“复选框 XYZ”),则会触发两次单击事件,并显示两次警报。

我猜这与复选框呈现为 HTML 的方式有关,如下所示:

<span class="test">
 <input id="ctl00_c1_cb1" type="checkbox" name="ctl00$c1$cb1" checked="checked"/>
 <label for="ctl00_c1_cb1">Checkbox XYZ</label>
</span>

如何正确设置 click 事件处理程序以防止它被调用两次?

【问题讨论】:

    标签: asp.net jquery checkbox


    【解决方案1】:

    好吧,在再次阅读我的问题后,我找到了解决方法。

    只需将“输入”添加到 jQuery 选择器:

    <script type="text/javascript">
    $(document).ready(function() {
            $('.test input').click(function() {
                    alert("click")
            })
    });
    </script>
    

    【讨论】:

    • @Martin - 我认为这是因为带有 for 属性的标签引发了附加元素的点击事件。因此,在您的 jQuery 代码中,您为标签和输入设置了一个单击事件处理程序。点击标签时,会执行你在标签上设置的点击事件处理程序,然后在标签引发点击事件时执行输入上设置的点击事件处理程序。
    • 点赞!当使用带有输入的标签时,我也遇到了同样的事情,更改为 div 并且它消失了
    【解决方案2】:

    您看到的是事件冒泡。点击事件首先由标签处理,然后传递给复选框。您会收到一个警报。为了防止事件冒泡,您需要在单击处理程序中返回 false。

    $(document).ready(function() {
            $('.test').click(function() {
                    alert("Click");
                    return false;
            })
    });
    

    但是,虽然这可以防止事件冒泡,但它也具有防止复选框更改状态的不良副作用。所以你需要围绕它编写代码。

    【讨论】:

      【解决方案3】:

      我认为这是因为带有for 属性的&lt;label&gt; 引发了与单击时关联的&lt;input type="radio"&gt;&lt;input type="checkbox"&gt; 元素的单击事件。

      因此,在您的 jQuery 代码中,您为 &lt;span class="test"&gt; 中的 &lt;label&gt;&lt;input&gt; 设置了一个点击事件处理程序。当点击&lt;label&gt; 时,您在标签上设置的点击事件处理程序将执行,然后在&lt;input&gt; 上设置的点击事件处理程序将在标签引发&lt;input&gt; 上的点击事件时执行。

      【讨论】:

      • 如果你把alert("click");改成alert(e.target.tagName);就可以看到这个——首先你看到LABEL然后INPUT,表示标签首先引发了一个点击事件,然后勾选/取消勾选关联的复选框,导致输入引发点击事件。
      【解决方案4】:
      $(document).ready(function() {
          $('.test').click(function(event) {
                          event.stopImmediatePropagation();
                          alert("Click");
                          })
                       }
                    );
      

      我能够通过停止事件传播使我的代码正常工作。不影响复选框的状态变化。

      【讨论】:

      • 不幸的是,这对我不起作用(在 IE8 中测试)。当我单击与复选框关联的标签/文本时,警报仍然显示两次。
      【解决方案5】:

      我刚刚经历了同样的事情,但不确定事件冒泡是否导致了我的问题。我有一个自定义树控件,当打开一个项目时,我使用$(id).click() 将处理程序附加到某种类型的所有元素。

      我怀疑这意味着其他地方已经有该事件的现有项目可能会再次添加它。我发现取消绑定所有内容然后重新绑定解决了我的问题,因此:

      $('img.load_expand').unbind("click").click(function()
      {
        // handler
      });
      

      【讨论】:

        【解决方案6】:

        已解决:这适用于 Firefox 3.6.12 和 IE8。

        $(function(){
                $("form input:checkbox").unbind("click")
                .click(function(){
                    val = $(this).val();
                    alert(val);
                })
            }
        

        诀窍是先绑定unbind("click").,然后再绑定.click(fn);这将禁止同一事件触发两次。

        请注意,第一次选中复选框时,事件“更改”不会欺骗。所以我改用“点击”。

        【讨论】:

          【解决方案7】:

          我在点击事件时遇到了同样的问题,并找到了this 文章。本质上,如果您在 &lt;body&gt;&lt;/body&gt; 标签,您可以获得多个事件。修复方法当然是不这样做,或者取消绑定单击事件并重新绑定它,如上所述。有时,对于多个 javascript 库,可能很难避免多个 document.ready(),因此 unbind 是一个很好的解决方法。

          <code>
          $('#my-div-id').unbind("click").click(function()
            {
              alert('only click once!');
            }
          </code>
          

          【讨论】:

            【解决方案8】:

            只需使用 .mouseup 而不是 .click

            【讨论】:

            • 这对我有用,但你能解释一下为什么它有效吗?有什么区别?
            【解决方案9】:

            函数运行两次。一次从内部调用,然后再次从内部调用它。简单的在最后添加一个return语句。

            <script type="text/javascript">
            $(document).ready(function() {
                $('.test').click(function() {
                    alert("click");
                    return false;
                })
            });
            </script>
            
            <asp:CheckBox runat="server" Text="Checkbox XYZ" CssClass="test" ID="cb1" />
            

            这对我来说非常有效。

            【讨论】:

              【解决方案10】:

              我知道这个问题现在已经解决了,但我刚刚遇到了同样的问题,我想添加我找到的解决方案,可能会在未来遇到类似问题时派上用场。

              当你添加 ASP 代码时:

              <asp:CheckBox runat="server" Text="Checkbox XYZ" CssClass="test" ID="cb1" />
              

              问题是&lt;asp:CheckBox ...&gt;不是一个html控件,它只是ASP 由一些精神病患者的扭曲的头脑发明的发明的,所以浏览器会收到别的东西。

              浏览器会收到类似的信息:

              <span class="test">
                  <input id="garbageforYourId_cb1" type="checkbox" name="garbage$moregarbage$cb1"/>
                  <label for="evenMoreGarbage_cb1">Checkbox XYZ</label>
              </span>
              

              许多可能的解决方案之一:

              浏览器会收到一个跨度,其中包含一个输入“复选框”和一个带有文本的标签。因此我的解决方案是这样的:

              $('.test > :checkbox').click(function() {
                  if ($(this).attr("checked")) {
                      alert("checked!!!");
                  } else {
                      alert("non checked!!!");
                  }
              });
              

              上面发生了什么?这个选择器$('.test &gt; :checkbox') 的意思是:找到具有“test”类的元素并带上它包含的任何复选框。

              【讨论】:

                【解决方案11】:

                我在选择器上遇到了同样的问题。最后使用off() 函数。

                $('body').off('click').on('click', '<your selector>', function(){
                    // Your code                
                });
                

                【讨论】:

                  猜你喜欢
                  • 2011-10-07
                  • 2011-08-29
                  • 2011-09-22
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2015-07-27
                  • 1970-01-01
                  • 2011-03-27
                  相关资源
                  最近更新 更多