window.onload = function(){
var wow = document.getElementById("wow");
wow.onclick = function(){
alert("hi");
}
}

<label id="wow"><input type="checkbox" name="checkbox" value="value">Text</label>
&#13;
这是我的代码,当我点击&#34; Text&#34;它会提示两次,但当我点击框时,onclick
元素只会触发一次,为什么?
答案 0 :(得分:45)
当您点击标签时,它会触发点击处理程序,然后您会收到提醒。
但是,单击标签也会自动向相关的输入元素发送单击事件,因此将其视为单击复选框。然后事件冒泡导致在包含元素(即标签)上触发click事件,因此您的处理程序将再次运行。
如果您将HTML更改为此,则无法获得双重警报:
<input id="wowcb" type="checkbox" name="checkbox" value="value">
<label id="wow" for="wowcb">Text</label>
现在,标签使用for
属性与复选框相关联,而不是环绕它。
答案 1 :(得分:3)
如果您的目的是仅响应标签上的点击而不是复选框,则可以查看 event.target 属性。它引用了调用侦听器的元素,以便如果单击不在该元素上,则不要执行该操作:
window.onload = function(){
var el = document.getElementById('wow');
el.addEventListener('click', function(event) {
if (this === event.target) {
/* click was on label */
alert('click was on label');
} else {
/* click was on checkbox */
event.stopPropagation();
return false;
}
}, false);
}
另一方面,如果您只想响应复选框上的点击(标签上的点击也会勾选复选框),则执行相反的操作。对标签上的点击不做任何操作,并从复选框中选择:
window.onload = function(){
var el = document.getElementById('foolabel');
el.addEventListener('click', function(event) {
if (this === event.target) {
/* click was on label */
event.stopPropagation();
return false;
} else {
/*
** click is from checkbox, initiated by click on label
** or checkbox
*/
alert('click from checkbox');
}
}, false);
}
这个版本似乎有最自然的行为。但是,更改标记以使标签不再包含复选框将意味着不会调用侦听器。
答案 2 :(得分:1)
事件泡沫。
复选框是标签的子节点。单击复选框。事件泡沫到标签。然后警报弹出两次。
单击复选框以防止警报弹出两次。您可以将onck功能更改为:
wow.onclick = function(e){
alert('hi');
stopBubble(e);
}
function stopBubble(e)
{
if (e && e.stopPropagation)
e.stopPropagation()
else
window.event.cancelBubble=true
}
希望这对你有用。
答案 3 :(得分:0)
Label标签将与其中的输入标签相关联。因此,当您单击标签时,它还会触发输入的单击事件,然后冒泡到标签本身。
见:
document.getElementById("winput").addEventListener('click', function(event){
alert('input click');
//stop bubble
event.stopPropagation();
}, false);
答案 4 :(得分:0)
再次将头撞到这个陷阱,并决定向自己证明它所做的事情,希望能帮助我记住。为了帮助可能对上述内容不够清楚的将来的人们,这里我举一个例子。
https://jsfiddle.net/ashes/0bcauenm/
$(".someBigContainer").on("click", "input[type=checkbox]", ()=> {
$output.val("Clicked: checkbox\n" + $output.val());
});
edit:添加带有代码片段的链接。
答案 5 :(得分:0)
这可能是最简单的答案。只需在文本周围添加一个跨度并停止事件传播。
window.onload = function(){
var wow = document.getElementById("wow");
wow.onclick = function(){
alert("hi");
}
}
<label id="wow">
<input type="checkbox" name="checkbox" value="value">
<span onclick="event.stopPropagation()">Text</span>
</label>
或者没有内联javaScript
window.onload = function(){
var wow = document.getElementById("wow");
wow.onclick = function(){
alert("hi");
}
var span = document.getElementsByTagName("span")[0];
span.onclick = function(event){
event.stopPropagation();
}
}
<label id="wow">
<input type="checkbox" name="checkbox" value="value">
<span>Text</span>
</label>
答案 6 :(得分:0)
对于那些使用 React 和 Material UI 的人 - 我在我的一个表单上遇到过这个问题。 event.preventDefault()
正在阻止事件冒泡,如已接受的答案所述。
<Button
onClick={(event) => {
event.preventDefault()
this.handleCardClick(planName)
}}
>
<FormControl component="fieldset">
<RadioGroup
row
value={selectedPlan}
>
<FormControlLabel
control={<Radio color="secondary" />}
label={label}
/>
</RadioGroup>
</FormControl>
</Button>