【问题标题】:jQuery Click fires twice when clicking on label单击标签时,jQuery Click 会触发两次
【发布时间】:2012-01-04 12:47:43
【问题描述】:

我正在使用 jQuery 创建自定义单选按钮,但我遇到了问题。 当点击与收音机关联的标签时,点击事件会触发两次,如果我只点击收音机本身它工作正常(实际上它不是我点击的收音机,而是包装整个输入和标签的 div)。代码如下:

HTML:

 <div id="box">
     <asp:RadioButtonList ID="RadioButtonList1" runat="server">
         <asp:ListItem>RADIO1</asp:ListItem>
         <asp:ListItem>RADIO2</asp:ListItem>
         <asp:ListItem>RADIO3</asp:ListItem>
     </asp:RadioButtonList>
</div>

jQuery:

<script type="text/javascript">
       $(function () {
            $('#box').find('input:radio').each(function (i) {

            var input = $(this);
            // get the associated label using the input's id
            var label = $('label[for=' + input.attr('id') + ']');
            // wrap the input + label in a div
            $('<div class="custom-radio"></div>').insertBefore(input).append(label, input);

            var wrapperDiv = input.parent();

            // find all inputs in this set using the shared name attribute
            var allInputs = $('input[name=' + input.attr('name') + ']');

            // necessary for browsers that don't support the :hover pseudo class on labels
            label.hover(

            function () {
                $(this).addClass('hover');
            }, function () {
                $(this).removeClass('hover checkedHover');
            });

            //bind custom event, trigger it, bind click,focus,blur events
            wrapperDiv.bind('updateState', function () {
                if ($(this)[0].children[1].checked) {
                    allInputs.each(function () {
                        var curDiv = $('div > label[for=' + $(this).attr('id') + ']').parent();
                        curDiv.removeClass('custom-radio-checked');
                        curDiv.addClass('custom-radio');
                    });
                    $(this).toggleClass('custom-radio custom-radio-checked');
                }
                else {
                    $(this).removeClass('custom-radio-checked checkedHover checkedFocus');
                }

            })
            .trigger('updateState')
            .click(function () { console.log('click'); })
            .focus(function () {
                label.addClass('focus');
            }).blur(function () {
                label.removeClass('focus checkedFocus');
            });
        }); 
       });
   </script>

这种行为有什么解决办法吗?

【问题讨论】:

    标签: jquery


    【解决方案1】:

    我尝试通过添加添加上述解决方案:

    evt.stopPropagation();
    evt.preventDefault();
    

    但是没有用。但是添加这个:

    evt.stopImmediatePropagation();
    

    解决了问题! :)

    【讨论】:

    • 我不知道为什么,但你所说的看起来适合我的代码。谢谢!
    • 完美。这很好用!虽然evt.stopPropagation(); evt.preventDefault(); 没有;'t
    • 只有这个对我有用,我试过其他功能都没有成功
    • 这个答案救了我的命!谢谢:D
    • 这就是我的答案!
    【解决方案2】:

    尝试添加:

    evt.stopPropagation();
    evt.preventDefault();
    

    到 .bind() 或 .click(),无论你看到什么。另外,在函数中添加参数evt,如function(evt) {...

    【讨论】:

    • 为什么会这样?
    • 因为有嵌套项。层次结构中的每个项目都会冒泡事件。
    • 如果您将其用于复选框,我也需要这样做才能实际检查输入:jQuery('input').prop('checked', true);
    • return false; 等价于 `evt.stopPropagation(); evt.preventDefault(); (在 jQuery 中
    【解决方案3】:

    将点击事件绑定到输入而不是标签。单击标签时 - 该事件仍会发生,因为正如 Dustin 所提到的,单击标签会触发对输入的单击。这将允许标签保持其正常功能。

    $('input').click();
    

    代替

    $('label').click();
    

    【讨论】:

    • 如果您的标记使用 label-wrapping-the-input 技术,此解决方案也适用,并且只是保存了我的理智 :o)
    • 你实际上应该绑定到change,即使是在单选按钮上,因为标签的文本是可点击的——它们并不总是点击单选按钮本身。
    • 如果使用 Bootstrapesque label &gt; input 设置,这是答案,而不是答案。将evt.stopPropagation()evt.preventDefault() 添加到您的代码中虽然有效,但当正确的解决方案更清洁、更高效时,应该避免这种技巧。
    • 哇哇哇哇,我花了将近几天的时间弄清楚,最后这有帮助,非常感谢您的解释
    • 这拯救了我的一天!
    【解决方案4】:

    如果您尝试使用外部容器作为点击元素,您还可以让事件自然冒泡并在点击处理程序中测试预期元素。如果您尝试为表单设置唯一点击区域的样式,此方案非常有用。

    <form>
    <div id="outer">
        <label for="mycheckbox">My Checkbox</label>
        <input type="checkbox" name="mycheckbox" id="mycheckbox" value="on"/>
    </div>
    </form>
    <script>
    $('#outer').on('click', function(e){
        // this fires for #outer, label, and input
        if (e.target.tagName == 'INPUT'){
            // only interested in input
            console.log(this);
        }
    });
    </script>
    

    【讨论】:

    • 这对我有用,因为我仍然希望选择单选按钮。我只是不希望事件处理程序对所有事情都做两次。
    • 这将不允许选择孩子。顺便说一句,实现相同功能的更好选择是if (e.target == e.currentTarget) {}
    【解决方案5】:

    要轻松解决此问题,请删除标签上的“for”属性。点击标签也会触发点击相关元素。 (在您的情况下会触发您的点击事件两次。)

    祝你好运

    【讨论】:

    • 确实是快速解决方案。有人可能会争辩说它弄乱了标记,但我反驳说“for”属性的目的是事件传播。因此,如果您使用另一种机制(jquery),那么一定要摆脱“for”。
    【解决方案6】:

    我通常使用这个合成器

    .off('click').on('click', function () { console.log('click'); })
    

    而不是

    .click(function () { console.log('click'); })
    

    【讨论】:

      【解决方案7】:

      最佳答案隐藏在 cmets 中:

      您实际上应该绑定到change,即使是在单选按钮上,因为 标签的文本是可点击的——他们并不总是点击收音机 按钮本身。 – chovy 2013 年 12 月 12 日 1:45

      这个fiddle 说明了所有其他解决方案——stopPropagationstopImmediatePropagationpreventDefaultreturn false——要么不做任何改变,要么破坏复选框/收音机功能)。它还说明这是一个普通的 JavaScript 问题,而不是 jQuery 问题。

      编辑: 我刚刚发现in another thread 的另一个可行解决方案是将onclick 绑定到输入而不是标签。 Updated fiddle.

      【讨论】:

        【解决方案8】:

        我尝试过添加解决方案。

        evt.stopPropagation();
        evt.preventDefault();
        

        但没用。

        通过添加

        evt.stopImmediatePropagation();
        

        解决了问题! :)

        【讨论】:

        • 我也有类似的情况,后者也对我有用
        【解决方案9】:

        e.preventDefault() 的问题;它是否会阻止标签单击检查单选按钮。

        更好的解决方案是简单地添加“已检查”快速检查,如下所示:

        $("label").click(function(e){
          var rbtn = $(this).find("input");
          if(rbtn.is(':checked')){
          **All the code you want to have happen on click**
          }
        )};
        

        【讨论】:

        • 更简洁的解决方案是使用 .mouseup 而不是 .click
        • 如果您的代码还允许用户取消选择单选按钮,则此解决方案不起作用。在这种情况下,双火造成了严重的麻烦。
        • @yoshyosh .mouseup 仅适用于鼠标操作。请记住,也可以使用键盘上的“空格键”键检查复选框。
        【解决方案10】:

        我的问题有点不同,因为evt.stopPropagation();evt.preventDefault(); 对我不起作用,我只是在最后添加return false;,然后就可以了。

        $("#addressDiv").on("click", ".goEditAddress", function(event) {
            alert("halo");
            return false;
        });
        

        【讨论】:

        • 这种情况下点击标签后没有点击复选框
        【解决方案11】:

        在我的情况下,问题是我在函数中有点击事件并且函数执行了两次....函数的每次执行都会创建一个新的点击事件。 -捂脸-

        将点击事件移到函数外后,一切都按预期进行! :)

        【讨论】:

          【解决方案12】:

          试着把你的输入标签放在触发元素之外,因为标签标签模拟点击,所以你总是会有多个调用。

          【讨论】:

            【解决方案13】:

            我遇到了同样的问题,因为我将收音机嵌套在这样的标签内,处理程序附加到 radio_div。移除嵌套标签解决了这个问题。

            <div id="radio_div">
                <label>
                   <input type="radio" class="community_radio" name="community_radio" value="existing">
                       Add To Existing Community
                </label>
            </div>
            

            【讨论】:

              【解决方案14】:

              标签触发单选框/复选框被选中。

              if ($(event.target).is('label')){
                  event.preventDefault();
              }
              

              它特别防止标签触发这种行为。

              【讨论】:

                【解决方案15】:

                点击带有 for="some-id" 属性的标签会触发新的点击,但前提是目标存在并且是输入。我无法用 e.preventDefault() 或类似的东西完美地解决它,所以我这样做了:

                例如,如果您有这种结构并希望在单击 .some-class 时发生事件

                <div class="some-class">
                    <input type=checkbox" id="the-input-id" />
                    <label for="the-input-id">Label</label>
                </div>
                

                起作用的是:

                $(document)
                    .on('click', '.some-class', function(e) {
                        if(
                            $(e.target).is('label[for]')
                            &&
                            $('input#' + $(e.target).attr('for')).length
                        ) {
                            // This will trigger a new click so we are out of here
                            return;
                        }
                
                        // else do your thing here, it will not get called twice
                    })
                ;
                

                【讨论】:

                  【解决方案16】:
                  $(document).on('click','.class',function() {
                      alert('abc')
                  })
                  

                  在我的情况下,它触发了 2 次,因为我将这段代码包含了 2 次,例如 assets/js/test.js 2 次。

                  【讨论】:

                    猜你喜欢
                    • 2013-06-15
                    • 2018-03-26
                    • 2017-12-19
                    • 2015-11-26
                    • 1970-01-01
                    • 2010-11-16
                    • 2014-01-08
                    • 1970-01-01
                    • 2016-05-05
                    相关资源
                    最近更新 更多