事件浅谈之事件冒泡

来源:互联网 发布:可视化布局系统 源码 编辑:程序博客网 时间:2024/06/07 11:49

什么是事件?

简单来说,事件就是文档或浏览器窗口发生的一些特定的交互瞬间。它最早时是用作分担服务器运算负载的一种手段。后来DOM2级规范开始尝试以一种符合逻辑的方式来标准化DOM事件。但是它并没有规范所有的事件类型。后来,DOM3级又增强了DOM事件的API。我们所熟悉的BOM也支持一些事件, 但BOM事件长期并没有规范,而且它支持的这些事件与DOM事件的关系也不太明确。使用事件有时复杂,有时相对简单,难度会因为需求的不同而不同。

事件流

事件流描述是从页面中接收事件的顺序。举例:
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Document</title><style type="text/css">div{padding:40px;}#div1{background:red;}#div2{background:blue;}#div3{background:green;}</style><script type="text/javascript">window.onload = function(){var oDiv1= document.getElementById('div1');var oDiv2 = document.getElementById('div2');var oDiv3 = document.getElementById('div3');function fn (){alert(this.id)}oDiv1.onclick = fn;oDiv2.onclick = fn;oDiv3.onclick = fn;}</script></head><body><div id="div1"><div id="div2"><div id="div3"></div></div></div></body></html>
效果展示:

当点击绿色DIV时,会依次弹出三次三个Id,分别是Div1、Div2、Div3。并不是因为他们的样式表现,而是因为html结构。如下代码,结果同上:
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Document</title><style type="text/css">div{padding:40px;}#div1{background:red;}#div2{background:blue;}#div3{background:green;position: absolute;top:300px;}</style><script type="text/javascript">window.onload = function(){var oDiv1= document.getElementById('div1');var oDiv2 = document.getElementById('div2');var oDiv3 = document.getElementById('div3');function fn (){alert(this.id)}oDiv1.onclick = fn;oDiv2.onclick = fn;oDiv3.onclick = fn;}</script></head><body><div id="div1"><div id="div2"><div id="div3"></div></div></div></body></html>
效果展示:
事件流包含两个内容:
  1. 事件冒泡流
  2. 事件捕获流

事件冒泡

先说一下,如果你点击了某个按钮,你也一定单击了它的父级,父级的父级的父级......
拿上述的两个例子,事件冒泡就是从事件开始的元素接收然后逐级向上传播到window对象,
<div>--><body>--><html>-->document
所有现代浏览器都支持事件冒泡,但在具体实现上还是有一些差别。IE5.5及更早版本中的事件冒泡会跳过<html>元素,其他浏览器(IE9、Firefox、Chrome、Safari)则将事件一直冒泡到window对象。
首先,点击oDiv1对象,然后触发点击事件,执行fn函数,然后传播事件到它的父级oDiv2,如果oDiv2接收到一个点击事件,那么他就执行fn函数。(事件函数绑定:把一个函数与事件进行绑定,事件发生时执行函数)再传播事件到oDiv2的父级oDiv3,如果oDiv3接收到一个点击事件,那么他就执行fn函数。
如果我们删除
oDiv2.onclick = fn;
这行代码,结果依然会弹出id为Div1的id,那么为什么会出现这种情况呢?因为这种操作并没影响oDiv2事件的发生和接收。会影响的只是事件发生以后要做的事情,即fn函数的执行,没有绑定就不会执行,所以没有显示,但是它还是会把事件传播给oDiv1,而oDiv1绑定了fn函数,所以,它弹出了oDiv1的id。

实例:下拉菜单

<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>Document</title><style type="text/css">div{width:100px;height:200px;border:1px solid #000;background:pink;display: none}</style><script type="text/javascript">window.onload = function(){var oBtn = document.getElementsByTagName('input')[0];var oDiv = document.getElementById('div')oBtn.onclick = function(){oDiv.style.display = "block";}document.onclick = function(){oDiv.style.display = 'none';}}</script></head><body><input type="button" value="下拉按钮"/><div id="div"></div></body></html>
执行的时候按钮怎么都不会打开下拉列表,因为当点击按钮的时候,触发点击事件,执行绑定函数:
function(){oDiv.style.display = "block";}
正常情况下,下拉列表会出现,但是因为下段代码出现导致出现没打开的现象
document.onclick = function(){oDiv.style.display = 'none';}
实际上,下拉列表打开了,因为时间太快所以并没有看见,在看不见的时间里,由于事件冒泡,oDiv把事件传播到了它的父级的父级的父级即document对象,document对象恰好有绑定的函数,它的功能是把oDiv的display属性值变为none,所以,在看不见的时间里,发生了确实发生的事情。为了看的更明显,可以加一个定时器。代码如下:
document.onclick = function(){setTimeout(function(){oDiv.style.display = 'none';},1000)//1s之后执行}

如此看来,事件冒泡好像变得有点麻烦,缺点变得显而易见,那么为什么还要把它设置为默认存在的呢?因为他的优点不可忽略。

事件冒泡的优点:

假如事件冒泡不存在,我们还是实现如上效果:点击按钮下拉出现,点击除按钮以为的任何元素下拉列表消失。
那么,我们要做的是给页面里除按钮以外的所有元素都加上点击事件,这样庞大的工程......像我是绝对做不下去的。但是如果有事件冒泡这种事件流,就很方便,我们 只需要给共同的父级加事件处理例如:body标签,利用事件冒泡,用任何一个子元素都会把事件传播给文档,让文档去做这件事,会轻松很多。解决上面出现的问题,只需要阻止oBtn的事件冒泡就可以了。
event.cancleBubble = true;//默认情况为false

实例:分享到



 
子级冒泡到父级

0 0
原创粉丝点击