解决点击label触发两次事件的bug

作者: bkbtp 分类: 前端 发布时间: 2018-05-12 14:05

选择单选或复选框时,为了好的用户体验(点击单选框或者复选框旁的文字,即可选中当前项),我们通常会使用label标签进行包裹或采用for–name对应。

形如:

<div class="radio-group layui-clear" id="datecheck">
    <label>
        <input type="radio" class="radio" name="cc" checked/>
        <span class="inp-radio">今日</span>
    </label>
    <label>
        <input type="radio" class="radio" name="cc" />
        <span class="inp-radio">昨日</span>
    </label>
    <label>
        <input type="radio" class="radio" name="cc" />
        <span class="inp-radio">本月</span>
    </label>
    <label>
        <input type="radio" class="radio" name="cc" />
        <span class="inp-radio">本年</span>
    </label>
</div>
var a = 0;
$('#datecheck label').on('click', function (e) {
    a++;
    console.log(a);
    console.log(e.target);
});

查看控制台:blob.jpg

可以得出结论:

当点击label的时候,事件冒泡一次,同时会触发关联的input的click事件,导致事件再次冒泡。

既然知道了问题所在,解决方案也很简单。

方案一

阻止label的默认行为,但同时绑定关联的效果也就失效了,一般不建议采用此方案。

$('#datecheck label').on('click', function (e) {
    a++;
    console.log(a);
    console.log(e.target);
    return false;  // 但同时绑定关联的效果也就失效了,一般不不建议
});

因为默认的radio比较丑,很多时候都会进行美化,配合上面的结构,加上如下css

.radio-group {
    display: inline-block;
    vertical-align: middle;
}

.radio-group label {
    float: left;
}

.radio {
    display: none;
}

.inp-radio {
    display: inline-block;
    padding: 5px 12px;
    line-height: 1.42857143;
    text-decoration: none;
    color: #494949;
    background-color: #fff;
    border: 1px solid #ddd;
    margin-left: -1px;
}

.radio-group label:first-child .inp-radio {
    border-bottom-left-radius: 4px;
    border-top-left-radius: 4px;
}

.radio-group label:last-child .inp-radio {
    border-bottom-right-radius: 4px;
    border-top-right-radius: 4px;
}

.radio:checked+.inp-radio {
    background-color: #409eff;
    border-color: #409eff;
    color: #fff;
}

可以得到如图效果: blob.jpg 美滋滋。

然而,这里需要判断raido的checked状态来改变高亮效果,如果禁止了label和radio的关联则会达不到预期的效果。

为了保证效果的实现,通常我们会使用方案二。

方案二

根据click事件的事件源进行相应操作,比如判断事件源为input,执行相应请求:

$('#datecheck label').on('click', function (e) {
    var date_type = $(this).index();
    if (e.target.tagName === 'INPUT') {
        getTable(date_type + 1, null);
        $('#date').val('')
    }
});

总体来说,方案二,既保证了效果的展示,也实现了相应的功能,美滋滋。

发表评论

电子邮件地址不会被公开。 必填项已用*标注

知识共享许可协议
本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。