事件流描述的是从页面中接受事件的顺序,当几个都具有事件的元素层叠在一起的时候,那么你点击其中一个元素,并不是只有当前被点击的元素会触发事件,而层叠在你点击范围的所有元素都会触发事件。
当一个DOM事件被触发时,它不仅仅只是单纯地在本身对象上触发一次,而是会经历三个不同的阶段:
捕获阶段:先由文档的根节点document往事件触发对象,从外向内捕获事件对象;
目标阶段:到达目标事件位置(事发地),触发事件;
冒泡阶段:再从目标事件位置往文档的根节点方向回溯,从内向外冒泡事件对象。
子集元素先触发,父级元素后触;(由内到外)
子集元素和父元素具备同样的事件,当触发子元素时,也会触发父元素的事件。
父级元素先触发,子集元素后触发;(由外到内)
IE不支持addEventListener和removeEventListener方法
第一个参数:必须。字符串,指定事件名。不要使用 “on” 前缀。 例如,使用 “click” ,而不是使用 “onclick”。
第二个参数:必须。指定要事件触发时执行的函数。
第三个参数:可选。布尔值,指定事件是否在捕获或冒泡阶段执行。
true - 事件句柄在捕获阶段执行
false- false- 默认。事件句柄在冒泡阶段执行
var element=document.getElementById("box");
var handler=function(){
event.preventDefault( ); //阻止默认事件
}
//绑定事件
element.addEventListener('click', handler, false);
//解绑事件
element.removeEventListener('click', handle, false);
有类似于addEventListener的方法:attachEvent();detachEvent(); 区别就是attachEvent()的参数只有两个且和addEventListener()前两个参数一致,只支持冒泡
var element=document.getElementById("box");
var handler=function(){
event.returnValue = false; //阻止默认事件
}
//绑定事件
element.attachEvent('onclick', handler);
//解绑事件,参数和绑定一样
element.detachEvent("onclick", handler);
//用事件冒泡方式,如果想兼容事件捕获只需要添加个bool参数
var EventUtil = {
addEvent: function(element,type,handler) {
if (element.addEventListener) {
element.addEventListener(type,handler,false);
}
else if (element.attachEvent) {
element.attachEvent('on'+type,handler);
}
else {
element['on'+type] = handler;
}
},
removeEvent: function(element,type,handler) {
if (element.removeEventListener)
{
element.removeEventListener(type,handler,false);
}
else if(element.detachEvent) {
element.detachEvent('on' +type,handler);
}
else {
element['on'+type] = null;
}
}
}
//如何调用
var box= document.getElementById("box");
var handler = function(){
console.log(111);
};
EventUtil.addEvent(box, "click", handler);
EventUtil.removeEvent(box, "click", handler);
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1">
<title></title>
<style>
#demo1 {
width: 300px;
height: 300px;
background: red;
}
#demo2 {
width: 200px;
height: 200px;
background: blue;
}
#demo3 {
width: 100px;
height: 100px;
background: yellow;
}
</style>
<script type="text/javascript">
window.onload = function() {
var demo1 = document.getElementById("demo1");
var demo2 = document.getElementById("demo2");
var demo3 = document.getElementById("demo3");
var fnDome = function() {
alert(this.id)
}
function fnStop() {
alert(this.id);
event.stopPropagation();
//event.stopPropagation() 阻止事件冒泡的产生
//Propagation(繁殖、传播 )
}
//单独一项一项测试时
//demo1.addEventListener("click", fnDome, false); //demo1,点击三个div都会弹出
//demo2.addEventListener("click", fnDome, false); //demo2,点击demo2,demo3两个div都会弹出
//demo3.addEventListener("click", fnDome, false); //demo3,点击demo3这个div
//demo1.addEventListener("click", fnDome, true); //demo1点击三个div都会弹出
//demo2.addEventListener("click", fnDome, true); //demo1,点击demo2,demo3两个div都会弹出
// demo3.addEventListener("click", fnDome, true); //demo1,点击demo3这个div
//demo1.addEventListener("click", fnStop, false); //demo1,点击三个div都会弹出
//demo2.addEventListener("click", fnStop, false); //demo2,点击demo2,demo3两个div都会弹出
//demo3.addEventListener("click", fnStop, false); //demo3,点击demo3这个div
//demo1.addEventListener("click", fnStop, true); //demo1,点击三个div都会弹出
//demo2.addEventListener("click", fnStop, true); //demo2,点击demo2,demo3两个div都会弹出
//demo3.addEventListener("click", fnStop, true); //demo3,点击demo3这个div
//事件处理函数不能加括号,否则会直接执行
//总结:当选中一个节点时,无论是冒泡还是捕获,里面的节点有同样的事件
//第二次测试,合并测试,当一个事假有多个节点时
// demo1.addEventListener("click", fnDome, false); //一次,demo1
// demo2.addEventListener("click", fnDome, false); //二次,demo2,demo1
// demo3.addEventListener("click", fnDome, false); //三次,demo3,demo2,demo1
//总结:冒泡事件按从内到外依次执行
//第三次测试,合并测试,当一个事假有多个节点时
// demo1.addEventListener("click", fnDome, true); //demo1
// demo2.addEventListener("click", fnDome, true); //demo1,demo2
// demo3.addEventListener("click", fnDome, true); //demo1,demo2,demo3
//总结:鋪貨事件按从外到内依次执行
//第四次测试,合并测试,当一个事假有多个节点时
// demo1.addEventListener("click", fnStop, false); //demo1
// demo2.addEventListener("click", fnStop, false); //demo2
// demo3.addEventListener("click", fnStop, false); //demo3
//第五次测试,合并测试,当一个事假有多个节点时
//demo1.addEventListener("click", fnStop, true); //demo1
demo2.addEventListener("click", fnStop, true); //demo1
demo3.addEventListener("click", fnStop, true); //demo1
}
</script>
</head>
<body>
<div id="demo1">1
<div id="demo2">2
<div id="demo3">3
</div>
</div>
</div>
</body>
</html>
总结:
(1)当选中一个节点时,无论是冒泡还是捕获,节点里面的节点有同样的事件
(2)当一个事件有多个节点时,冒泡事件按从内到外依次执行
(3)当一个事件有多个节点时,捕获事件按从外到内依次执行
(4)当一个事件有多个节点时,阻止事件冒泡的产生,冒泡事件,只会执行当前或包含的节点事件,不会冒泡,执行完里面节点的事件不会接着执行包含节点的节点事件,也就是说只会执行一次,如果不阻止事件冒泡的产生,则会将事件一个个执行完
(5)当一个事件有多个节点时,阻止事件冒泡的产生,捕获事件,只会执行第一个捕获到的事件
preventDefault 它是事件对象(Event)的一个方法,作用是取消一个目标元素的默认行为。比如超链接a
<body>
<a href="事件冒泡.html" target="_blank">啦啦啦啦啦</a>
<script type="text/javascript">
var a1=document.getElementsByTagName('a')[0];
//传统用法阻止事件的默认发生
// a1.οnclick=function(e){
// e.preventDefault();
// }
//使用DOM方法来阻止默认发生
a1.addEventListener('click',show);
//兼容
function show(e){
if (e.preventDefault) {
e.preventDefault();
} else{
window.event.returnValue=false;
}
}
</script>
</body>