为什么onclick元素会为label元素触发两次

dra*_*sea 27 html javascript

      window.onload = function(){
         var wow = document.getElementById("wow");
    	 wow.onclick = function(){
    	     alert("hi");
    	 }
      }
Run Code Online (Sandbox Code Playgroud)
    <label id="wow"><input type="checkbox" name="checkbox" value="value">Text</label>
Run Code Online (Sandbox Code Playgroud)

这是我的代码,当我点击"文字"时它会提示两次,但当我点击框时,该onclick元素只会触发一次,为什么?

Bar*_*mar 50

当您单击标签时,它会触发单击处理程序,并且您会收到警报.

但是单击标签也会自动将click事件发送到关联的input元素,因此将其视为单击复选框.然后事件冒泡导致在包含元素(即标签)上触发click事件,因此您的处理程序将再次运行.

如果您将HTML更改为此,则不会获得双重警报:

<input id="wowcb" type="checkbox" name="checkbox" value="value">
<label id="wow" for="wowcb">Text</label>
Run Code Online (Sandbox Code Playgroud)

现在,标签使用for属性与复选框相关联,而不是环绕它.

DEMO

  • 理想情况下,将绑定更改事件处理程序.非常适合无障碍. (4认同)
  • 我实际上遇到过这种情况.很烦人. (3认同)

Rob*_*obG 5

如果您只想响应标签上的点击而不是复选框上的点击,您可以查看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);
}
Run Code Online (Sandbox Code Playgroud)

另一方面,如果您只想响应点击复选框(点击标签也会产生点击复选框),然后执行相反的操作。对标签上的点击什么也不做,让复选框中的点击通过:

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);
}
Run Code Online (Sandbox Code Playgroud)

这个版本似乎有最自然的行为。但是,更改标记以使标签不再包裹复选框将意味着不会调用侦听器。