DOM模型是一个树形结构,在DOM模型中,HTML元素是有层次的。当一个HTML元素上产生一个事件时,该事件会在DOM树中元素节点与根节点之间按特定的顺序传播,路径所经过的节点都会收到该事件,这个传播过程就是DOM事件流。
当事件发生后,这个事件就要开始传播(从里到外或者从外向里)。为什么要传播呢?因为事件源本身(可能)并没有处理事件的能力,即处理事件的函数(方法)并未绑定在该事件源上。例如我们点击一个按钮时,就会产生一个click事件,但这个按钮本身可能不能处理这个事件,事件必须从这个按钮传播出去,从而到达能够处理这个事件的代码中(例如我们给按钮的onclick属性赋一个函数的名字,就是让这个函数去处理该按钮的click事件),或者按钮的父级绑定有事件函数,当该点击事件发生在按钮上,按钮本身并无处理事件函数,则传播到父级去处理。
DOM事件标准定义了两种事件流,分别是捕获事件和冒泡事件。
事件捕获指的是从document到触发事件的那个节点,即自上而下的去触发事件。相反的,事件冒泡是自下而上的去触发事件。
来看一个实例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>事件冒泡</title>
<script type="text/javascript" src="../jquery-1.11.2.min.js"></script>
<style type="text/css">
#a {
width: 200px;
height: 200px;
background-color: gray;
}
#b {
width: 100px;
height: 100px;
background-color: pink;
}
</style>
</head>
<body>
<div id="a">
<div id="b">
<a href="http://www.baidu.com" target="_blank">百度一下</a>
</div>
</div>
<script type="text/javascript">
document.getElementById("a").addEventListener("click", function(e) {
console.log("a事件被触发," + this.id);
}, true);
document.getElementById("b").addEventListener("click", function(e) {
console.log("b事件被触发," + this.id);
}, true);
</script>
</body>
</html>
绑定事件方法的第三个参数,就是控制事件触发顺序是否为事件捕获。true,事件捕获;false,事件冒泡。默认false,即事件冒泡。所以当你对一个dom节点触发事件时,若外层的节点也设置了相应的事件函数,就会使外层的节点也触发自己的事件函数。
当两个都为false时,结果为:
点击a,只触发a事件:
点击b,同时ab事件(先b后a,事件冒泡):触发
当两个都为true时:
点击a,只触发a事件:
如果想要阻止事件冒泡:
event.stopPropagation()方法
这是阻止事件的冒泡方法,不让事件向documen上蔓延,但是默认事件任然会执行,当你掉用这个方法的时候,如果点击一个连接,这个连接仍然会被打开。阻止事件冒泡只需要将event.stopPropagation()插入到console.log前。阻止事件a冒泡,第三个参数为false,将event.stopPropagation()插入到b事件函数的console.log前,结果,点击b,只执行b:
event.preventDefault()方法---阻止事件默认事件eg:表单提交,页面跳转
这是阻止默认事件的方法,调用此方法是,连接不会被打开,但是会发生冒泡,冒泡会传递到上一层的父元素。
return false ;
它会同时阻止事件冒泡也会阻止默认事件;写上此代码,连接不会被打开,事件也不会传递到上一层的父元素;可以理解为return false就等于同时调用了event.stopPropagation()和event.preventDefault()
阻止事件冒泡 event.stopPropagation():
如果点击方法时需要同时传递其他参数和event,直接传递event这个单词即可
事件委托:
当有多个类似的元素需要绑定事件时,一个一个去绑定即浪费时间,又不利于性能,这时候就可以用到事件委托,给他们的一个共同父级元素添加一个事件函数去处理他们所有的事件情况。e.target表示在事件冒泡中触发事件的源元素,在IE中是e.srcElement
并且e.target有很多属性可以操作
event.target.nodeName //获取事件触发元素标签name(li,p…)
event.target.id //获取事件触发元素id
event.target.className //获取事件触发元素classname
event.target.innerHTML //获取事件触发元素的内容(li)