jQuery复选框事件处理

157

我有以下代码:

<form id="myform">
   <input type="checkbox" name="check1" value="check1">
   <input type="checkbox" name="check2" value="check2">
</form>

如何使用jQuery来捕获myform中发生的任何复选框事件,并告诉我切换了哪个复选框(以及它是否被打开或关闭)?

7个回答

284
$('#myform :checkbox').change(function() {
    // this will contain a reference to the checkbox   
    if (this.checked) {
        // the checkbox is now checked 
    } else {
        // the checkbox is now no longer checked
    }
});

30
this 已经被设置为复选框的 DOM 元素,因此 this.checked 就足够了。除非你打算操作它,否则不需要为它创建另一个 jQuery 对象。 - Walf
19
只是一个小提示。在选择器中使用input:checkbox而不仅仅是:checkbox,您将获得性能提升,因为后者被转换为通用选择器*:checkbox。 - jimmystormig
24
Click事件与任何一种检查事件都没有丝毫相似之处。 - Peter
28
这不是最佳答案。如果您对输入有相应的标签(例如 <label for='myInput'>Checkbox:</label><input id='myInput' name='myInput' type='checkbox'/> ),并且单击标签,则将选中复选框,但不会调用此功能。您应该使用 .change() 事件。 - Patrick
7
这个回答没有完全解答问题 - 请看下面 Anurag 的回答,那是一个更完整(和准确)的答案。当然,这个回答部分正确,但作为陈述,它并不是最好的答案。 - Carnix
显示剩余3条评论

134

使用change事件。

$('#myform :checkbox').change(function() {
    // this represents the checkbox that was checked
    // do something with it
});

5
如果复选框被隐藏了,用户就无法与它进行交互。如果您的意思不是这个,请告诉我。 - Anurag
2
这不会触发 $("input[name=check1]").prop('checked', true)。请参见 http://jsfiddle.net/Z3E8V/2/。 - Peter
15
这是有意为之的。通过编程方式更改DOM元素的属性不会触发相关的事件处理程序。你需要手动触发它们。 - Anurag
6
这应该是选定的答案,它涵盖了点击复选框标签的内容。 - Patrick
3
根据 jQuery 文档:"由于 :checkbox 是 jQuery 的扩展而不是 CSS 规范的一部分,所以使用 :checkbox 进行查询时无法利用本地 DOM querySelectorAll() 方法提供的性能提升。为了在现代浏览器中获得更好的性能,请改用 [type="checkbox"]。" - NXT
显示剩余2条评论

58

有几个有用的答案,但似乎没有涵盖所有最新的选项。为此,我的所有示例还应考虑匹配的

  • 监听复选框上的click事件不是一个好主意,因为这不允许键盘切换或更改匹配的

  • 使用jQuery的:checkbox伪选择器,而不是input[type=checkbox]。:checkbox更短更易读。

  • 使用is()和jQuery的:checked伪选择器来测试复选框是否已选中。这保证适用于所有浏览器。

附加到现有元素的基本事件处理程序:

$('#myform :checkbox').change(function () {
    if ($(this).is(':checked')) {
        console.log($(this).val() + ' is now checked');
    } else {
        console.log($(this).val() + ' is now unchecked');
    }
});

JSFiddle: http://jsfiddle.net/TrueBlueAussie/u8bcggfL/2/

注意事项:

  • 使用:checkbox选择器优于使用input[type=checkbox]
  • 此事件处理程序仅连接到在注册事件时已存在的匹配元素。

委托给祖先元素的事件处理程序:

委托事件处理程序适用于元素尚不存在(动态加载或创建)的情况,非常有用。它们将责任委托给祖先元素(因此称为“委托”)。

$('#myform').on('change', ':checkbox', function () {
    if ($(this).is(':checked')) {
        console.log($(this).val() + ' is now checked');
    } else {
        console.log($(this).val() + ' is now unchecked');
    }
});

JSFiddle: http://jsfiddle.net/TrueBlueAussie/u8bcggfL/4/

说明:

  • 通过监听事件(在本例中为change)冒泡到不变的祖先元素(在本例中为#myform)来实现。
  • 然后将jQuery选择器(在此为':checkbox')应用于气泡链中的元素。
  • 然后将事件处理程序函数仅应用于引起事件的匹配元素。
  • 如果没有更接近/方便的元素,请使用document作为连接委派事件处理程序的默认值。
  • 不要使用body附加委派事件,因为它有一个错误(与样式有关),可能会阻止它获得鼠标事件。

委托处理程序的结果是,匹配的元素只需要存在于事件发生时,而不需要在事件处理程序注册时存在。这允许动态添加的内容生成事件。

Q:速度会慢吗?

A: 只要事件处于用户交互速度,您不需要担心委派事件处理程序和直接连接处理程序之间微不足道的速度差异。委派的好处远远超过任何小缺点。委托事件处理程序实际上是更快的注册,因为它们通常连接到单个匹配元素。


为什么prop('checked', true)不触发change事件?

这实际上是设计如此。如果它触发了该事件,您很容易陷入无休止更新的情况。相反,在更改已选中属性后,使用trigger(而不是triggerHandler)向同一元素发送一个更改事件:

例如,没有trigger不会发生事件

$cb.prop('checked', !$cb.prop('checked'));

JSFiddle: http://jsfiddle.net/TrueBlueAussie/u8bcggfL/5/

例如,使用trigger会捕获正常的更改事件。

$cb.prop('checked', !$cb.prop('checked')).trigger('change');

JSFiddle: http://jsfiddle.net/TrueBlueAussie/u8bcggfL/6/

Notes:

  • 不要使用一个用户建议的triggerHandler,因为它无法将事件冒泡到一个被委托的事件处理程序。

JSFiddle: http://jsfiddle.net/TrueBlueAussie/u8bcggfL/8/

虽然对于一个直接连接到元素上的事件处理程序而言,它确实可以工作:

JSFiddle: http://jsfiddle.net/TrueBlueAussie/u8bcggfL/9/

使用.triggerHandler()触发的事件不会向DOM层次结构中上溯传播;如果它们没有被目标元素直接处理,则什么也不会发生。

参考资料:http://api.jquery.com/triggerhandler/

如果有人认为还有其他未涵盖的特性,请建议添加。


我通过这个答案发现了.trigger('change')。非常感谢这个非常完整的答案! - Pierre
在子元素上委托事件处理程序时加上+1。实际上,我需要这个功能来处理一些复杂的动态代码,你刚刚帮我省去了很多补丁式编码,这对于父元素更加合适。 - DarrenMB

34

使用 jQuery 中的新 'on' 方法 (1.7 版本):http://api.jquery.com/on/

    $('#myform').on('change', 'input[type=checkbox]', function(e) {
        console.log(this.name+' '+this.value+' '+this.checked);

    });
  • 事件处理程序将继续存在
  • 如果复选框是通过键盘而不仅仅是点击更改的,则会捕获

1
这不会触发 $("input[name=check1]").prop('checked', true)。请参见 http://jsfiddle.net/Z3E8V/2/。 - Peter
7
.prop调用之后添加.triggerHandler('change');即可。这样它将切换该框并触发事件。 - Hanna
另一种方法: $(document).on('change','input[type="checkbox"]', function() { $('input[type="checkbox"]').not(this).prop('checked', false); }); - Yoosaf Abdulla

6
承认提问者明确要求使用jQuery并且所选答案是正确的,但需要注意的是这个问题实际上并不一定需要jQuery。如果想要在没有jQuery的情况下解决这个问题,可以简单地设置想要添加额外功能的复选框的onClick属性,如下所示:
HTML:
<form id="myform">
  <input type="checkbox" name="check1" value="check1" onClick="cbChanged(this);">
  <input type="checkbox" name="check2" value="check2" onClick="cbChanged(this);">
</form>

JavaScript:

function cbChanged(checkboxElem) {
  if (checkboxElem.checked) {
    // Do something special
  } else {
    // Do something else
  }
}

Fiddle: http://jsfiddle.net/Y9f66/1/


5
将事件处理程序直接放入HTML中当然可以工作,但它与DRY和渐进增强方法直接冲突。更准确的答案应该是“您不需要jQuery来添加事件处理程序”,而是使用标准JS在单独的JS文件中附加点击处理程序,而不是将onclick属性放入HTML中。这样做“可以工作”,但良好的编程实践指出,除非必须支持IE6或其他版本,否则应尽可能避免使用此方法(目前几乎总是如此,甚至连微软也建议不再支持IE6)。 - Carnix

5
$('#myform input:checkbox').click(
 function(e){
   alert($(this).is(':checked'))
 }
)

val() 无法告诉你 checked 是否为 true - Walf

4

我尝试了第一个答案的代码,但它没有起作用。不过我进行了一些尝试,这个代码对我有效。

$('#vip').change(function(){
    if ($(this).is(':checked')) {
        alert('checked');
    } else {
        alert('uncheck');
    }
});

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