为什么即使在alert()之前调用了preventDefault(),alert()仍会执行?

时间:2019-09-22 10:54:34

标签: javascript dom-events event-bubbling

在下面的代码中,为何触发alert('Alert on btn is triggered') }),即使在event.preventDefault() el的click处理程序的此行之前调用#btn

此外,为什么onclick="alerted()不会在#btn#wrap的div上触发,但回调触发是通过click触发的,附加到addEventListener上。

var btn = document.getElementById('btn')
var wrap = document.getElementById('wrap')

btn.addEventListener('click', function() {
  event.stopPropagation()
  if (event.cancelable) {
    event.preventDefault()
  }
  alert('Alert on btn is triggered')
})


function alerted() {
  alert('Alerted fired')
}

wrap.addEventListener('click', function() {
  alert(this.id)
  alert(event.target.tagName + "#" + event.target.id)
})
#wrap {
  padding: 20px;
  border: 1px solid red;
}
<div id="wrap" onclick="alerted">
  <button id="btn" onclick="alerted">Click Me</button>
</div>

3 个答案:

答案 0 :(得分:6)

调用event.preventDefault()event.stopPropagation不会停止当前正在进行的回调。 无论函数的上下文如何,如果函数开始运行,阻止它继续运行的唯一方法就是显式return

如果要确保在调用preventDefault()时该函数的其余部分停止运行,请更改为:

  if (event.cancelable) {
    event.preventDefault();
    return;
  }

最好将event定义为处理程序接受的参数,而不要依赖隐式全局window.event(尽管它可以正常工作在某些浏览器中为not a great idea to use)。

var btn = document.getElementById('btn')
var wrap = document.getElementById('wrap')

btn.addEventListener('click', function(event) {
  event.stopPropagation()
  if (event.cancelable) {
    event.preventDefault();
    return;
  }
  alert('Alert on btn is triggered')
})


function alerted() {
  alert('Alerted fired')
}

wrap.addEventListener('click', function() {
  alert(this.id)
  alert(event.target.tagName + "#" + event.target.id)
})
#wrap {
  padding: 20px;
  border: 1px solid red;
}
<div id="wrap" onclick="alerted">
  <button id="btn" onclick="alerted">Click Me</button>
</div>

答案 1 :(得分:1)

说明:您的点击事件中警报不是默认设置,无论是否调用event.preventDefault();都会触发警报。

preventDefault()取决于默认事件。例如:在点击事件上使用preventDefault()可以防止点击触发器,或者在按下键盘上使用preventDefault()可以防止默认的键盘按下事件。

就像当前答案一样,要阻止警报,请使用return;

此外,我刚刚注意到,您的代码onclick="alerted"应该为onclick="alerted()"

更新:

说明1:由于被阻止,该警报不会在btn中触发。您将alerted()放在onclick上,就阻止了click事件。 换句话说,警报位于点击内部,因此单击被阻止,因此警报不会触发。

说明2:按钮是对象而不是事件,对象可以具有相同的事件。例如:div是容器,但是您可以在它们上使用click事件。

答案 2 :(得分:-2)

由于即使在您停止事件传播时触发事件,它也不会在其他事件侦听器中触发,但是您的函数将继续执行。