为什么阻止了div的默认行为,里面的a标签就不跳转网站了?

我阻止了div的默认行为,里面的a就不跳转了。

代码:

<div>
    <a href="http://www.baidu.com">跳转百度</a>
</div>
<script>
    var div = document.getElementsByTagName("div")[0];
    div.onclick = function(event){
        event.preventDefault();
    };
</script>    

问题:
a标签不跳转了,但是div本身没有任何默认行为啊,阻止div的默认行为,为何会阻止a的跳转。

猜想一:

a标签的页面跳转行为是由window来执行的,在事件传播的过程中,中止掉了这个传递过程。

猜想二:

但是用stoppropagation(),并不能阻止,说明事件传播和行为传播是两个线程?

阅读 9.9k
10 个回答

div上的click事件a标签也继承了,所以实际上a标签上也绑定了click事件。所以才不能触发

表示事件的确是绑定在 div 标签上
clipboard.png

再看 a标签 上有没有事件?

clipboard.png

实际上 a标签本身并未定义事件。再看下面这张图:

clipboard.png

注意图中的:

clipboard.png

表示显示继承的事件。

然后结果是:a标签 继承了 divclick事件
所以才会导致 a标签 不能跳转了。

其实在 div 上加 click 事件,和直接在 a 标签上加事件,event 是同一个,这就好理解了。

var div = document.getElementsByTagName("div")[0];
div.onclick = function(event){
    e1 = event;
    event.preventDefault();
};

var a = document.getElementsByTagName("a")[0];
a.onclick = function(event){
    e2 = event;
    event.preventDefault();
};

// 页面打开后快速点击
setTimeout(() => alert(e1 === e2), 4000)  // true

首先,不要不看手册瞎猜,况且事件根本没有继承一说。
看到这个问题,的确也打破了我之前对事件机制的认识。首先我们知道事件机制分为捕获阶段和冒泡阶段,捕获阶段事件从window一直传播到元素本身,然后开始冒泡阶段,冒泡阶段事件再从元素本身传播到window。下面我们看手册是怎么说的(https://developer.mozilla.org...:

clipboard.png

e.preventDefault() 可以在任何阶段阻止事件,并且该方法不会阻止该事件的进一步冒泡。在该例中,a 本身的 click 事件是被触发了的,但当该事件冒泡到递到 div 时,div调用 e.preventDefault() 方法, 该方法将 e.defaultPrevented 修改为 true, 这样当时间传递到 window 时 e.defaultPrevented === true,默认操作不执行。为了验证,这里写段代码验证一下:

<div>
    <a href="http://www.baidu.com">跳转百度</a>
</div>
<script>
    var div = document.getElementsByTagName("div")[0];
    var a = document.getElementsByTagName("a")[0];
    a.onclick = () => {
        console.log('click A');
    };
    div.onclick = (e) => {
        console.log('click DIV');
        e.preventDefault();
    };
    window.onclick = (e) => {
        console.log('window', e.defaultPrevented);
    };
</script>  

理解这个问题,重要是理解事件周期,你定义了两个事件,其实是一个事件在其传播周期内的两个不同阶段。

1.
其实是点击a,冒泡到div,触发div的onclick,执行了当前事件的阻止默认行为,就不跳转了。
2.
给a的点击事件加了stoppropagation()是能够正常跳转的。因为看不到代码不知道是我理解错误你的意思还是你加错了位置。
3.
事件的默认行为是在事件的所有你写的代码执行完毕才会被执行。

event.preventDefault()是阻止某个事件的默认行为,与哪个元素无关,所以即使你是给div绑定click事件,也是会阻止a标签的click事件的默认行为,个人观点

在 a 标签的 onclick 事件中调用 stopPropagation() 则 不管 div 的 onclick 事件中是否调用了 preventDefault() 都无法阻止 a 标签的默认行为.
所以我推测,事件的默认行为是否被阻止是在事件传播结束后结算的,即在事件传播结束后回调默认行为函数

就是事件冒泡而已。单击 a 产生 click 事件 event.target === a 。事件冒泡,委托 div 进行处理

event.preventDefault()

既然阻止了默认事件 那就不跳转了。

新手上路,请多包涵

这应该是时间捕获吧!

a 的 click 事件冒泡到 div,
div 收到的事件其实就是 a 传过来的事件。
所以阻止默认行为就阻止 a 的 click 事件的默认行为,即跳转。
这里不是什么事件捕获,就是一个冒泡。
你说的通过 stopPropagation 不能阻止,然而我亲自试了一下,此时是能够跳转的,因为 a 的事件被阻止传播,从而没有冒泡到 div ,也就没有被 div 阻止该事件的默认行为。


<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title></title>
  </head>
  <body>
    <div>
    <a id="x" href="http://www.baidu.com">跳转百度</a>
</div>
<script>
    var a = getElementById('x');
    a.onclick = function(e) {
      e.stopPropagation();
    }
    var div = document.getElementsByTagName("div")[0];
    div.onclick = function(event){
        event.preventDefault();
    };
</script>
  </body>
</html>
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题