点击标签不会触发点击事件。

11

我有这段代码:

<label><input type="checkbox">True?</label>

$("label").click(function () {
  $(this).toggleClass("active");
});

当我点击复选框时,类被切换,但当我点击“True?”时没有任何反应。为什么?

如果我不将复选框包装在标签中,则一切都正常运作。

<input type="checkbox" id="c1"><label for="c1">True?</label>

这太奇怪了...而且加不加“for”都无所谓。

http://jsfiddle.net/zufs6ueh/1/

这里出了什么问题?


3
onclick 会触发两次吗?label 以一种特定的方式与 input 进行交互。 - Halcyon
我不确定是为什么,可能是因为当输入框包含在标签中时,标签的点击事件被重定向到了输入框上。但解决方法可以是将事件绑定到输入框并更改父级标签的类名,例如 $("label input").click(function () { $(this).parent('label').toggleClass("active"); }); - Dave Goten
@Halcyon 是的,看起来 onclick 会触发两次,因为我在 Web Inspector 中看到了空的“class”。这个问题能修复吗? - artemean
3个回答

12
这样使用会更安全:
$(function() {

    $('input[type="checkbox"]').bind('change', function (v) {

        if($(this).is(':checked')) {
            $(this).parent().addClass('active');
        } else {
            $(this).parent().removeClass('active');
        }
    });

});

使用change而不是click可以让那些使用键盘导航表单的人更加方便。


1
你的回答很好,建议在输入框上绑定事件,而不是所有标签上。无论如何,如果你说“允许使用键盘浏览表单的人”时意味着使用空格键来选中复选框,那么我认为没有任何问题,因为空格键也会触发click事件。+1 - DontVoteMeDown
@DontVoteMeDown 谢谢,我不知道空格键可以触发“点击”。每天都能学到新东西!但是你说得对,这里的主要问题是将事件附加到复选框而不是标签。 - rwacarter
正如之前提到的,当点击标签时,“click”事件会触发两次。您可以在“click”函数的末尾添加evt.stopPropagation(); evt.preventDefault();来防止这种情况发生。(并将evt作为函数的参数) - rwacarter
@rwacarter,是的,但为什么它会触发两次?这不奇怪吗?也许是个bug?;-) - artemean
这太棒了 :) 谢谢 - hkucuk
显示剩余3条评论

2
点击标签还会触发输入框的点击事件,因此将改变事件绑定到复选框本身:

$(function(){
    $("label input").on("click",function(){
 $(this).parent().toggleClass("active");
    });
});
.active {color:red;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<label><input type="checkbox" />True?</label>

或者使用CSS 3

如果您不需要支持旧的浏览器,您可以使用CSS中的:checked伪类:

input[type=checkbox]:checked + label {color:red;}
<input type="checkbox" id="demo" name="demo"> 
<label for="demo">True?</label> 


我一直是避免不必要使用JavaScript的粉丝,但是提醒一下,在IE<9中:checked伪类将无法工作。 - rwacarter
@rwacarter - 同意。很烦人,不是吗?理想情况下,您应该测试支持,然后使用JS回退。 - Moob
@Moob,你的代码做了@rwacarter建议的相同的事情,但仍然不清楚为什么onclick会触发两次...至于JS,我需要在标签被点击后执行其他操作,所以不能避免它。 - artemean

1
你离成功不远了,以下是关于HTML inputs的一些值得注意的事情:
  • HTML中radiocheckbox表单元素都可以通过onclick调用JavaScript函数

  • radiocheckbox类型的HTML表单元素都有一个.checked属性,可以被JavaScript检查,并且在CSS中使用:checked伪类

  • radio HTML表单元素上使用name允许对它们进行分组

这里有一些示例代码,可以使用checkbox执行某些操作...

/**
 * Example JavaScript function for HTML input radio or checkbox types to call
 * @returns {boolean}
 */
function checkCheckbox(checkbox) {
  if (checkbox.checked != true) return false;
  /* Do JavaSript things when checkbox is checked */
  console.log('checkbox.checked -> ' + checkbox.checked);
  window.alert('checkbox.value -> ' + checkbox.value);
  return true;
}
/**
 * Hide things that should not be seen by just anyone
 */
.menu__checkbox,
.menu__container {
  display: none;
  visibility: hidden;
  opacity: 0;
  filter: alpha(opacity=0); /* Old MS compatibility */
}

/**
 * Stylize the label some
 */
.menu__label {
  display: block;
  width: 20px;
  height: 100%;
  transform: rotate(90deg);
}


/**
 * Show some things when checkbox is checked
 * Note, if feeling adventurous try using a `~` instead of `+`
 */
.menu__checkbox:checked + .menu > .menu__container {
  display: block;
  visibility: visible;
  opacity: 1;
  filter: alpha(opacity=100);
}

/**
 * Oh and un-rotate label when checkbox is checked too
 */
.menu__checkbox:checked + .menu > .menu__label {
  transform: rotate(0deg);
}
<input type="checkbox"
       class="menu__checkbox"
       value="valuable_checkbox"
       onclick="checkCheckbox(this);"
       id="trigger-menu">


<div class="menu">

  <div class="menu__container">
    <p class="menu__description">
      Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
      tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
      proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
    </p>
  </div>

  <label for="trigger-menu"
         class="menu__label">
         &#x25B2;
  </label>

</div>

......如果你仔细观察,通过trigger-menu实现labelforinputid之间的目标定位会利用CSS和HTML完成一些许多人可能会使用JavaScript来完成的操作......尽管将复选框放置到菜单范围之外只是为了演示;换句话说,仅仅因为可以做某事并不总是意味着应该

就像我所暗示的那样,这个问题的代码非常接近......

<input type="checkbox" id="c1"><label for="c1">True?</label>

...可能与以下内容相关联:

<input id="c1" type="checkbox" onclick="window.alert('this.checked -> ' + this.checked);">
<label for="c1">Is checked?</label>

同时,我也暗示了radio typed inputs可以类似地使用,以下是一些可能在某个荒谬的东西中公开的预览内容...

    <div class="menu__style">
      <input type="radio"
             name="colorize"
             value="Default"
             onclick="color_picker.unsetAlternateStyleSheet()"
             class="menu__style__item"
             id="style-default">
      <label for="style-default"
             class="menu__style__label">Default Style</label>
      <br>

      <input type="radio"
             name="colorize"
             value="AlternateStyleOne"
             onclick="color_picker.setAlternateStyleSheet(title = this.value)"
             class="menu__style__item"
             id="style-one">
      <label for="style-one"
             class="menu__style__label">First Alternative Style</label>
      <br>

      <input type="radio"
             name="colorize"
             value="AlternateStyleTwo"
             onclick="color_picker.setAlternateStyleSheet(title = this.value)"
             class="menu__style__item"
             id="style-two">
      <label for="style-two"
             class="menu__style__label">Second Alternative Style</label>
    </div>

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