首先从字面意思来看:

  • preventDefault 是指阻止默认事件
  • stopPropagation 是指停止传播

javascript 中的两种 “事件传播” 模式:

  • 捕获模式 (capturing):当事件发生时,该事件首先被最外层元素接受到,然后依次向内层元素传播。(从上向下,由外往里)
  • 冒泡模式 (bubbling):当事件发生时,该事件首先被最内层元素接受到,然后依次向外层元素传播。(从下向上,由里往外)


# preventDefault:

html

<a href="http://www.baidu.com" id="open">open</a>

javascript

document.getElementById("open").addEventListener("click",function(e){
  console.log("in");
},true);

直接点击 open,控制台会先输出 in,然后跳转到百度的页面,在这里,a 标签的默认事件是跳转页面,click 事件是我们自己添加的事件。

如果想只执行我们添加的事件而不进行跳转,这时候需要添加 preventDefault 来阻止 a 标签的默认事件

document.getElementById("inner").addEventListener("click",function(e){
  e.preventDefault();
  console.log("in");
},true);

这是点击 open,只会在控制台输出 in


# stopPropagation:

html

<div class="out">
  out
  <div class="middle">
    middle
    <div class="in">in</div>
  </div>
</div>

css

.out{
  width:300px;
  height:300px;
  border:1px solid #000;
  padding:10px;
  box-sizing:border-box;
  background:#ddd;
}
.middle{
  width:200px;
  height:200px;
  border:1px solid #000;
  padding:10px;
  box-sizing:border-box;
  background:skyblue;
}
.in{
  width:100px;
  height:100px;
  border:1px solid #000;
  padding:10px;
  box-sizing:border-box;
  background:tomato;
}

javascript

document.querySelector(".out").addEventListener("click",function(e){
  console.log("out");
},false);
document.querySelector(".middle").addEventListener("click",function(e){
  console.log("middle");
},false);
document.querySelector(".in").addEventListener("click",function(e){
  console.log("in");
},false);

效果:

img

注意现在 addEventListener 的最后一个参数为 false,为冒泡模式,即由里往外传播

这时点击红色区域(最里层 in)
控制台输出:

img

可以看出事件由里往外传播(in -> middle -> out)
如果这时候需要只显示 in,而不向外传播,就可以给 in 对应的标签事件使用 stopPropagation

document.querySelector(".in").addEventListener("click",function(e){
  e.stopPropagation();
  console.log("in");
},false);

控制台输出:

img

# 现在我们将三个元素的 addEventListener 的最后一个参数改为 true,这时候事件模式为捕获模式,即由外向里传播

document.querySelector(".out").addEventListener("click",function(e){
  console.log("out");
},true);
document.querySelector(".middle").addEventListener("click",function(e){
  console.log("middle");
},true);
document.querySelector(".in").addEventListener("click",function(e){
  console.log("in");
},true);

这时点击红色区域(最里层 in)
控制台输出:

img

可以看出事件由外往里传播(out -> middle -> in)
如果这时候需要只显示 out,而不向外传播,就可以给 out 对应的标签事件使用 stopPropagation

document.querySelector(".out").addEventListener("click",function(e){
  e.stopPropagation();
  console.log("out");
},true);

控制台输出:

img