为什么在此html / css / jquery中注册了两个点击事件 [英] Why are two click events registered in this html/css/jquery

查看:78
本文介绍了为什么在此html / css / jquery中注册了两个点击事件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试设置复选框列表的样式。我已经添加了样式,它们在渲染时会正确显示。单击复选框的标签时,我想添加一个类。这是我的标记,并且此处在jsfiddle中相同。从我的小提琴中可以看到,只有一次单击就注册了两个单击事件。为什么?

I am trying to style a checkbox list. I've added my styles and they appear correctly when rendered. I want to add a class when the label for the checkbox is clicked. This is my markup and here is the same in a jsfiddle. You can see from my fiddle that two click events are registered with just one click. Why?

html:

<ul>
    <li>
        <label for="test_0" class="">
            <input id="test_0" name="offering_cycle" type="checkbox" value="1"> Fall
        </label>
    </li>
    <li>
        <label for="test_1" class="">
            <input id="test_1" name="offering_cycle" type="checkbox" value="2"> Spring
        </label>
    </li>
    <li>
        <label for="test_2" class="">
            <input id="test_2" name="offering_cycle" type="checkbox" value="3"> Summer
        </label>
    </li>
    <li>
        <label for="test_3" class="">
            <input id="test_3" name="offering_cycle" type="checkbox" value="4"> Other
        </label>
    </li>
</ul>

css:

ul {
    list-style-type:none;
}
label {
    position:relative;
    display:inline-block;
    padding-left:27px;
    height:25px;
}
label:before {
    display:block;
    position:absolute;
    top:-2px;
    margin-left:-28px;
    width:18px;
    height:18px;
    background-color:#fff;
    border-radius:5px;
    border:1px solid #ccc;
    text-align: center;
    color:#fff;
    font-size:18px;
    content:'a';
}
input {
    width:1px;
    height:1px;
    border:0;
    opacity:0;
    float:right;
}

jquery:

$('label[for*=test_]').on('click',function(){
    $(this).toggleClass('testing');
});


推荐答案

原因是标签的单击处理程序被调用了两次:

单击与输入关联的标签会触发两个单击事件。标签会触发首次点击事件。该单击事件的默认处理会导致为关联的输入触发第二个单击事件。由于您将输入作为标签的后代,因此第二个click事件冒泡到标签。这就是为什么您的点击事件处理程序被调用两次的原因。

Clicking on a label that is associated with an input causes two click events to be triggered. The first click event is triggered for the label. The default handling of that click event causes a second click event to get triggered for the associated input. Since you have the input as a descendant of the label, the second click event bubbles up to the label. That is why your click event handler is called twice.

如果您确实要处理点击事件,标签(只需单击一次即可执行):

(1)如果您愿意并能够修改HTML,则可以移动输入,因此它不是标签的后代。仍然会有两个单击事件,但是第二个单击事件不会从输入到标签冒泡,因为标签不再是输入的祖先。

(1) If you are willing and able to modify the HTML, you could move the input so it is not a descendant of the label. There will still be two click events, but the second click event will not bubble up from the input to the label since the label is no longer an ancestor of the input.

如果输入不是标签的后代,则必须使用标签的 for属性将其与输入关联。 for属性的值应为输入的 id值。 (您已经在 for属性中添加了正确的值。)

When the input is not a descendant of the label, you must use the label's "for" attribute to associated it with the input. The value of the "for" attribute should be the "id" value of the input. (You are already including the "for" attribute with the proper value.)

<input id="test_0" name="offering_cycle" type="checkbox" value="1">
<label for="test_0" class="">Fall</label>






(2)防止默认处理第一个click事件可防止触发第二个click事件, 但这样做会破坏标签 。也就是说,单击标签时不会选中/取消选中该复选框。


(2) Preventing the default handling of the first click event prevents the second click event from getting triggered, BUT doing this breaks the label. That is, the checkbox will not get checked/unchecked when the label is clicked.

$('label[for*=test_]').on('click', function(event) {
    event.preventDefault();
    $(this).toggleClass('testing');
    // returning false would be another way to prevent the default handling.
});

jsfiddle

(3)相反,您可以阻止第二个单击事件从输入冒泡

(3) Instead, you could stop the second click event from bubbling up from the input.

$('input:checkbox').on('click', function(event) {
    event.stopPropagation();
});

$('label[for*=test_]').on('click', function() {
    $(this).toggleClass('testing');
});

jsfiddle

注意:如果输入的内容不是标签的子项,则没有必要。

Note: If the input was not a child of the label, this would not be necessary.

(4)或者您可以在处理程序中检查事件目标。这将是第一次单击事件的标签,而将是第二次单击事件的输入。以下处理程序仅对首次点击事件在if语句内执行代码。

(4) Or you could check the event target in the handler. It will be the label for the first click event and the input for the second. The following handler executes the code inside the if-statement only for the first click event.

$('label[for*=test_]').on('click', function(event) {
    if (event.target == this) {
        $(this).toggleClass('testing');
    }
});

jsfiddle

注意:如果输入的内容不是标签的子项,则上面的代码仍然有效,但if语句为

Note: If the input was not a child of the label, the code above would still work, but the if-statement would be unnecessary because the click event triggered for the input would not bubble up to the label.

为输入触发的点击事件不会冒泡到标签。

Handling the click for the input instead:

在您的情况下,您实际上不需要注册label元素的点击处理程序。您可以改为为输入注册点击(或更改)处理程序。然后,您可以使用 $(this).closest('label')来获取标签元素。

In your case, you don't really need to register a click handler for the label element. You could register a click (or change) handler for the input instead. You could then use $(this).closest('label') to get the label element.

$('input[name=offering_cycle]').on('click', function() {
     $(this).closest('label').toggleClass('testing');
});

jsfiddle

注意:如果输入的内容不是标签的子代,则单击标签时仍会调用上面的处理程序,但是 $(this).closest('label')无法获取标签。您必须使用类似 $('label [for ='+ this.id +']')的东西。

Note: If the input was not a child of the label, the handler above would still get called when you click on the label, but $(this).closest('label') would not get the label. You would have to use something like $('label[for="' + this.id + '"]') instead.

关于标签元素上的 for属性:

由于标签内有输入,因此不必在标签上包含 for 属性---但这不是无效的。

Since you have the inputs inside the labels, it is not necessary to include the for attributes on the labels --- but it's not invalid.

已将 for属性值设置为输入元素的 id属性值。这是使用 for属性将标签与输入关联的正确方法。如果要包含带有无效值的 for属性,则即使输入是标签的后代,标签也不会与输入关联。

You have set the "for" attribute values to the values of the "id" attributes of the input elements. That is the correct way to use the "for" attribute to associated a label with an input. If you were to include a "for" attribute with an invalid value, the label would not be associated with the input, even if the input is a descendant of the label.

HTML5规范中获取 for属性标签元素:

From the HTML5 spec for the "for" attribute of a label element:


可以指定for属性,以指示与标题关联的
的表单控件。如果指定了属性,则属性
的值必须是与标签元素相同的
文档中可标签元素的ID。如果指定了属性并且
,则文档中有一个元素的ID等于
的for属性的值,并且第一个此类元素是可标记的元素,
然后是该元素是标签元素的标签控件。

The for attribute may be specified to indicate a form control with which the caption is to be associated. If the attribute is specified, the attribute's value must be the ID of a labelable element in the same Document as the label element. If the attribute is specified and there is an element in the Document whose ID is equal to the value of the for attribute, and the first such element is a labelable element, then that element is the label element's labeled control.

如果未指定for属性,但是label元素具有
标签元素后代,则第一个此类后代树
订单是标签元素的标签控件。

If the for attribute is not specified, but the label element has a labelable element descendant, then the first such descendant in tree order is the label element's labeled control.

这篇关于为什么在此html / css / jquery中注册了两个点击事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆