为什么html标签用于触发回调包含div两次?

时间:2014-10-01 15:24:33

标签: javascript html

我看到another question提出类似的问题,但不同之处在于他们将输入元素放在label标记内,而我的标记在外面:

<!DOCTYPE html>
  <head>
    <style>
      div {
        background-color: #AAA;
        width: 100px;
      }
    </style>
  </head>

  <body>

    <div id='foo' onClick="alert('clicked')">
      <label for='foo-pie'>Pick Foo:</label>
      <select id='foo-pie' name='wat[wat]'>
        <option value='pie'>Foo</option>
      </select>
    </div>
  </body>
</html>

如果我点击div,而不是标签,警报会触发一次。如果我点击标签,警报会触发两次。为什么是这样?在我看来,无论如何警报应该触发一次。如果我删除for=它只会触发一次,这表明我发生了某种事件冒泡...... JSFiddle

2 个答案:

答案 0 :(得分:4)

这是因为label是一个交互元素。单击时,它会在其关联元素上触发激活事件。此激活事件通常会导致单击事件,因此您只需单击两次即可。一个用于实际用户点击,一个用于激活事件。

http://www.w3.org/TR/html5/forms.html#the-label-element

  

例如,在单击复选框标签的平台上检查   复选框,单击以下代码段中的标签可能会触发   用户代理在输入上运行合成点击激活步骤   元素,就好像元素本身已被用户触发:

     

<label><input type=checkbox name=lost> Lost</label>

     

另一方面   平台,行为可能只是集中控制,或做   什么都没有。

虽然文档中的示例显示了输入元素的onClick,但事件会冒出来,所以在您的情况下,您的div会获得冒泡的点击事件

Interactive-content doc

要防止这种情况,您可以阻止默认操作,或使用stopPropagation来阻止事件冒泡。

<强>内联

<label onclick="return false;" for='foo-pie'>Pick Foo:</label>

代码

HTML

<label id="foolabel" for='foo-pie'>Pick Foo:</label>

JS

document.getElementById("foolabel").addEventListener(function(e){
   e.preventDefault(); //Or
   e.stopPropagation();
});

示例

&#13;
&#13;
<div id='foo' onClick="alert('clicked')">
  <label onclick="event.stopPropagation();" for='foo-pie'>Pick Foo:</label>
  <select id='foo-pie' name='wat[wat]'>
    <option value='pie'>Foo</option>
  </select>
</div>
&#13;
&#13;
&#13;

答案 1 :(得分:0)

我的理论是,这是一个称为事件传播的功能,通过使用<div>属性定义onclick,它也会以某种方式将该事件绑定到孩子身上。

尝试将e.stopPropagation投放到您的事件回调中,并且应该阻止它被多次调用。

MDN Example