label标签和Input标签的关联

115 阅读2分钟

背景:在使用AI生成一个原生代码实现的switch组件时遇到一个问题,点击标签时会触发两次input的click事件

<label style="width:100%; margin: 16px; display: flex; align-items: center; font-size: 16px; color: #222831;background-color: white; border-radius: 8px;justify-content: space-between">
    <span style="margin-right: 20px;">是否开启手势密码</span>
    <input type="checkbox" id="gestureSwitch" style="
        display: none;
      ">
    <span id="switchButton" style="
        display: inline-block;
        width: 50px;
        height: 28px;
        background-color: #ccc;
        border-radius: 14px;
        position: relative;
        cursor: pointer;
        transition: background-color 0.3s;
      ">
        <span style="
          width: 24px;
          height: 24px;
          background-color: white;
          border-radius: 50%;
          position: absolute;
          top: 2px;
          left: 2px;
          transition: left 0.3s, transform 0.3s;
        "></span>
    </span>
</label>

<script>
    // 获取复选框和滑块元素
    const checkbox = document.getElementById('gestureSwitch');
    const slider = document.querySelector('.slider');
    checkbox.addEventListener('click', function (val) {
        console.log(val, "监听点击事件")
    })
    const switchButton = document.getElementById('switchButton');
    switchButton.addEventListener('click', function () {
        console.log("click----------------------------------------")
        checkbox.click()
    });
    // 监听复选框的变化
    checkbox.addEventListener('change', function () {
        console.log("change--------------------------------")
        const switchElement = document.getElementById('switchButton');
        // 设置滑块的位置
        if (this.checked) {
            switchElement.style.backgroundColor = '#0090fa'; // 绿色
            switchElement.firstElementChild.style.left = 'calc(100% - 26px)';
            switchElement.firstElementChild.style.transform = 'translateX(4px)';
        } else {
            switchElement.style.backgroundColor = '#ccc'; // 灰色
            switchElement.firstElementChild.style.left = '2px';
            switchElement.firstElementChild.style.transform = 'translateX(0)';
        }
        console.log('手势密码状态:', this.checked);
    });

    // 初始状态检查
    if (checkbox.checked) {
        checkbox.click();
    }
</script>

结果

经过搜索资料后发现label和input标签可以形成关联关系

1.显示绑定

label标签设置一个for属性,并将其值设置为对应input元素的id。这样,当用户点击这个label时,与之相关联的input元素也会被选中或触发事件。

一个input标签可以受到多个label标签的关联

<label for="myInput">点击我</label>
<input type="checkbox" id="myInput" style="display:none;">

<label for="controlInput">label1</label>
<label for="controlInput">label2</label>
<label for="controlInput">label3</label>
<input type="text" id="controlInput"
    style="width: 100%; padding: 12px; border-radius: 8px; border: 1px solid #ccc; margin-bottom: 16px;"/>

2. 隐性绑定

当input标签在label标签的内部时,会形成隐性绑定关系,导致点击label标签时也会触发内部隐藏的input标签的点击事件

<label> 元素可同时有一个 for 属性和一个子代控件元素,只是 for 属性需要指向这个控件元素。

<label for="myInput">
<span>点击我<span/>
<input type="checkbox" id="myInput" style="display:none;">
</label>

扩展

label的for属性:即和 <label> 元素在同一文档中的 可关联标签的元素 的 id。文档中第一个 id 值与 <label> 元素 for 属性值相同的元素,如果可关联标签(labelable),则为已关联标签的控件,其标签就是这个 <label> 元素。如果这个元素不可关联标签,则 for 属性没有效果。如果文档中还有其他元素的 id 值也和 for 属性相同,for 属性对这些元素也没有影响。

可关联的元素标签:<button><input><meter><output><progress><select> 和 <textarea>