html label 标签 onclick 事件执行两次原因以及解决方法

label 标签常用于包装表单元素,比如 radio checkbox input 等,如果给 label 绑定上 onclick 事件,触发事件会被执行两次,一个不算 bug 的 bug。

常见写法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<div>计数:<span id="js_output_1">0</span></div>

<label id="js_label_1"><input type="radio" className="radio__input" />点击试试</label>

<script>
(function () {
var out = document.getElementById('js_output_1');
var label = document.getElementById('js_label_1');
var i = 0;
label.addEventListener('click', function (e) {
out.innerHTML = ++i;
console.log(e.target.tagName);
}, false);
})();
</script>
  • 示例:
计数:0

打开 F2 控制台,可以看到触发事件的两个元素分别是 LABELINPUT

解决办法

方法一:使用 event.preventDefault() 阻止默认行为。

缺陷:此方法会导致 radio 标签的选中效果失效。

  • 源码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    <div>计数:<span id="js_output_3">0</span></div>

    <label id="js_label_3"><input type="radio" className="radio__input" />点击试试</label>

    <script>
    (function () {
    var out = document.getElementById('js_output_3');
    var label = document.getElementById('js_label_3');
    var i = 0;
    label.addEventListener('click', function (e) {
    out.innerHTML = ++i;
    e.preventDefault();
    console.log(e.target.tagName);
    }, false);
    })();
    </script>
  • 示例:

    计数:0

方法二:将 input 移到 label 外面,使用 id 属性关联。

注意 input 标签的 id 属性必须与 label 标签的 for 属性一样。

  • 源码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    <div>计数:<span id="js_output_2">0</span></div>

    <input id="radio" type="radio" className="radio__input" />
    <label for="radio" id="js_label_2">点击试试</label>

    <script>
    (function () {
    var out = document.getElementById('js_output_2');
    var label = document.getElementById('js_label_2');
    var i = 0;
    label.addEventListener('click', function (e) {
    out.innerHTML = ++i;
    console.log(e.target.tagName);
    }, false);
    })();
    </script>
  • 示例:

    计数:0

方法三:使用 event.target.tagName 判断标签是否是 label。

  • 源码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    <div>计数:<span id="js_output_4">0</span></div>

    <label id="js_label_4"><input type="radio" className="radio__input" />点击试试</label>

    <script>
    (function () {
    var out = document.getElementById('js_output_4');
    var label = document.getElementById('js_label_4');
    var i = 0;
    label.addEventListener('click', function (e) {
    if (e.target.tagName.toLocaleLowerCase() !== 'label') {
    return;
    }
    out.innerHTML = ++i;
    console.log(e.target.tagName);
    }, false);
    })();
    </script>
  • 示例:

    计数:0

—end—

本文由 linx(544819896@qq.com) 创作,采用 CC BY 4.0 CN协议 进行许可。 可自由转载、引用,但需署名作者且注明文章出处。本文链接为: https://blog.jijian.link/2020-05-18/html-label-onclick/

如果您觉得文章不错,可以请我喝一杯咖啡!