单击标签时,jQuery Click会触发两次

ton*_*one 107 jquery

我正在使用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>
Run Code Online (Sandbox Code Playgroud)

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>
Run Code Online (Sandbox Code Playgroud)

这种行为有什么解决方案吗?

N3d*_*3da 180

我尝试添加以下解决方案:

evt.stopPropagation();
evt.preventDefault();
Run Code Online (Sandbox Code Playgroud)

但没有奏效.但是添加这个:

evt.stopImmediatePropagation();
Run Code Online (Sandbox Code Playgroud)

解决了这个问题!:)

  • 完善.这很好用!虽然`evt.stopPropagation(); evt.preventDefault();`didn;'t (8认同)
  • 我不知道为什么,但你所说的看起来像我的代码.谢谢! (6认同)

Jor*_*dan 123

尝试添加:

evt.stopPropagation();
evt.preventDefault();
Run Code Online (Sandbox Code Playgroud)

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

  • 为什么会这样? (8认同)
  • 因为有嵌套的项目.层次结构中的每个项目都会使事件冒出来. (7认同)
  • 如果你使用它作为一个复选框,我也需要这样做才能实际检查输入:`jQuery('input').prop('checked',true);` (7认同)
  • `return false;`相当于`evt.stopPropagation(); evt.preventDefault(); (**在jQuery**) (6认同)

dou*_*knz 66

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

$('input').click();
Run Code Online (Sandbox Code Playgroud)

代替

$('label').click();
Run Code Online (Sandbox Code Playgroud)

  • 如果你的标记使用标签包装输入技术,这个解决方案也有效,并且只是保存了我的理智:o) (8认同)
  • 你甚至应该在单选按钮上绑定到`change`,因为标签的文本是可点击的 - 它们并不总是单击单选按钮本身. (4认同)
  • 如果使用 Bootstrapesque `label &gt; input` 设置,这就是答案,而不是答案。将 `evt.stopPropagation()` 或 `evt.preventDefault()` 添加到你的代码中,虽然有效,但当正确的解决方案更清晰、更高效时,应该避免这种黑客攻击。 (2认同)

tob*_*ius 11

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

<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>
Run Code Online (Sandbox Code Playgroud)


小智 8

要以简单的方式解决此问题,请删除标签上的"for"属性.单击标签也会触发相关元素的单击.(在您的情况下,两次点击事件.)

祝好运


小智 7

我尝试过添加解决方案。

evt.stopPropagation();
evt.preventDefault();
Run Code Online (Sandbox Code Playgroud)

但没有用。

通过增加

evt.stopImmediatePropagation();
Run Code Online (Sandbox Code Playgroud)

解决了问题!:)


Dal*_*bor 5

我通常会使用这种合成胶

.off('click').on('click', function () { console.log('click'); })
Run Code Online (Sandbox Code Playgroud)

代替

.click(function () { console.log('click'); })
Run Code Online (Sandbox Code Playgroud)


Woo*_*eru 5

最佳答案隐藏在评论中:

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

这个小提琴说明了所有其他解决方案 – stopPropagation, stopImmediatePropagation, preventDefault, return false– 要么什么都不改变,要么破坏复选框/收音机功能)。它还说明这是一个普通的 JavaScript 问题,而不是一个 jQuery 问题。

编辑: 我刚刚在另一个线程中找到的另一个工作解决方案是将 the 绑定onclick到输入而不是标签。更新了小提琴