事件委托/事件冒泡/事件捕获&&阻止事件冒泡/阻止事件默认行为
程序员文章站
2022-05-13 16:01:49
...
要了解事件委托,首先要了解事件流的概念和事件执行流程:
DOM2级中同时支持两种事件模型:捕获型事件和冒泡型事件 ,并且每当某一事件发生时,都会经过捕获阶段->处理阶段->冒泡阶段(有些浏览器不支持捕获) ;事件的捕获阶段是由上层元素到下层元素的顺序依次。而冒泡阶段则正相反。
当事件触发时body会先得到有事件发生的信息,然后依次往下传递,直到到达最详细的元素,这就是事件捕获阶段。
还记得事件注册方法ele.addEventListener(type,handler,flag)吧,Flag是一个Boolean值,true表示事件捕捉阶段执行,false表示事件冒泡阶段执行,默认为false。
接着就是事件冒泡阶段。从下往上 依次执行事件处理函数(当然前提是当前元素为该事件注册了事件句柄)。,在这个过程中,可以阻止事件的冒泡,即停止向上的传递。
想一个例子:你一定有过经历,给一个ul的所有li添加点击事件,然后用了一个循环,给每个li都添加了onclick监听事件,这是很危险的做法,理论上,如果li足够多,就足以造成点击某个li的一瞬间浏览器崩溃。所以这时候就要用到事件捕获,将点击事件绑定在li的父元素中,当点击事件发生时,父元素会在其子元素中层层查找一直到达触发事件那个最详细元素的位置(即触发事件的最内层元素),下面是一个例子,大家可以参考一下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>事件冒泡/事件捕获&&阻止事件冒泡/阻止事件默认行为</title>
<style>
div.div_in{
width: 200px;
height: 100px;
border: solid red 1px;
}
div.div_in_in{
width: 150px;
height: 50px;
border:1px solid black;
}
</style>
</head>
<body>
<div id="div_one" onclick="eventHandle(event)">
<ul id="ul_one">
<li id="li_one"><div id="one" class="div_in">1</div></li>
<li id="li_two"><div id="two" class="div_in">2</div></li>
<li id="li_three"><div id="three" class="div_in">3</div></li>
</ul>
</div>
<div id="div_two">
<ul id="ul_two">
<li id="li_four">
<div id="four" class="div_in" onclick="showNum('11111')">4
<div id="seven" class="div_in_in" onclick="showNum('22222')">7</div> <!-- 当该元素被点击时,弹出两个框,是由于onclick事件在当前div触发的同时又冒泡到其外层div,同时触发了外层div的onclick事件 -->
</div>
</li>
<li id="li_five">
<div id="five" class="div_in">5
<a href="http://www.baidu.com" target="_blank" onclick="notTurnToHerf(event)">turn to www.baidu.com</a>
</div>
</li>
<li id="li_six">
<div id="six" class="div_in" onclick="showNumStop(event,'33333')">6
<div id="eight" class="div_in_in" onclick="showNumStop(event,'44444')">8</div> <!-- 当该元素被点击时,只弹出“44444”框,因为冒泡事件被以下的stopBubble()方法阻止 -->
</div>
</li>
</ul>
</div>
<script>
function eventHandle(e){ //不是所有的事件都能冒泡,例如以下事件就不可以冒泡:blur、focus、load、unload
e = e || window.event; //获取事件对象(兼容浏览器->IE下的全局对象window.event和其他浏览器下的事件对象e;因为IE中没有e这个事件对象)
var obj = e.target || e.srcElement; //找到发生本次事件的源(兼容浏览器->IE下的e.srcElement以及其他浏览器下的e.target)
console.log(obj.id + ' was click');
}
function showNum(data){
console.log(data);
}
function showNumStop(e,data){
console.log(data);
stopBubble(e); //调用函数
}
function stopBubble(e){
e = e || window.event;
if(e.stopPropagation){
e.stopPropagation(); //非IE浏览器取消事件冒泡
console.log('已经阻止事件向上冒泡');
}else{
e.cancelBubble = true; //IE浏览器取消事件冒泡
console.log('已经阻止事件向上冒泡');
}
}
function notTurnToHerf(e){ //取消事件的默认行为,比如取消<a href="">的跳转行为
e = e || window.event;
if (e.preventDefault) {
e.preventDefault(); //非IE浏览器取消事件默认行为
console.log('已经阻止事件a的默认跳转行为');
} else {
e.returnValue = false; //IE浏览器取消事件默认行为;注意:不可用return false代替的,return false只能取消元素
console.log('已经阻止事件a的默认跳转行为');
}
}
</script>
</body>
</html>
上一篇: 短信验证码