背景:在使用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>。