0 前言
先看我准备的一个示例代码:
<body>
<form>
<label id="boyLabel">
Boy: <input type="radio" name="gender" id="boy" value="boy">
</label>
<br>
<label for="girl">Girl:</label>
<input type="radio" name="gender" id="girl" value="girl">
</form>
<script type="text/javascript">
const l1 = document.querySelector("#boyLabel");
const l2 = document.querySelector("label[for=girl]");
const i1 = document.querySelector("input[value=boy]");
const i2 = document.querySelector("input[value=girl]");
console.log(l1);
console.log(l2);
console.log(i1);
console.log(i2);
l1.addEventListener("click", (e) => {
console.log("l1 clicked! LLL1111");
});
l2.addEventListener("click", (e) => {
console.log("l2 clicked! LLL2222");
});
i1.addEventListener("click", (e) => {
// 这里注意,等下我要把下面的注释符号去掉,让它停止冒泡传播,来对比观察效果
// e.stopPropagation();
console.log("i1 clicked! III111");
});
i2.addEventListener("click", (e) => {
e.stopPropagation();
console.log("i2 clicked! III222");
});
</script>
</body>
我准备了一组关于性别的单选按钮,
采用了label和input标签的两种搭配使用方式,
一种: 对于男孩,采用label内包裹input标签,这种情况下就无需进行input标签先设定id, 然后label内for属性再绑定这个id,形成对应关系
另一种: 对于女孩的选项,采用最正统也就是官方网站示例一般采用的方式, 彼此独立开,用 for id绑定的形式来创建
script 标签内代码逻辑是: 先选定元素,打印出来看看选的对不对,然后分别给他们绑定click事件,便于观察后续的冒泡事件,
1 好戏开始
1.1 先点击 女孩选项的那个input
可见,这里只单单触发了 i2 的click 事件
1.2 再点击 女孩选项的那个label
这次,因为label和input进行了绑定,所以当我们点击label时,先是label被触发了,之后其绑定的input也被触发了
1.3 这次先点击 男孩选项的那个input
先是input标签被点击,没有问题,因为我们直接点的就是那个input, 之后发现,它外面的label也被点击了,这就是因为产生了冒泡的缘故,冒泡到了他的父元素即label标签,同样触发了它的click事件。
对于冒泡阶段不清楚的可以参考我这篇文章:
DOM的三种事件模型和牵扯到的事件e.
其中事件传播处的解释
1.4 再点击 男孩选项的那个label
我们发现,点击了label,label先被触发没有问题,然后是其绑定的input,再然后就和上面我们看到的那种情况一样了,因为input在label内部,所以它被触发后,进而冒泡,所以label又被触发了一次,因为冒泡嘛,
这样算下来,就是label会被触发了两次,没必要嘛,所以我们想想办法,毕竟这样比label和input独立开来那种多触发了一次label,
想到了,那就从input入手,阻止它冒泡不就行了
1.5 再点击 男孩选项的那个input 【阻止冒泡后】
把示例代码中 // e.stopPropagation(); 前面的 // 去掉
我们发现,label不会被触发了,只有点到的input触发了, 回顾之前,那可是label也要被触发的啊, 效果不错
1.6 再点击 男孩选项的那个label【阻止冒泡后】
此时,我们可以看到, 点击了label, label先触发,然后是它绑定的input,然后就没有了,如我们所愿,这样就和input,label都独立出来的女孩的那种现象一致了,也没有多余的触发,
2 那两种到底有什么区别呢?
就是没啥区别,唯一的一个优点吧,就是input嵌套在label里, 这样你就不用写for,id的绑定了,更方便一点,其他的样式什么的,都该怎么调怎么设置,
大家可以参考下这个问答: