js之事件冒泡和事件捕获介绍
链接:http://www.jb51.net/article/42492.htm
(1)冒泡型事件:事件按照从最特定的事件目标到最不特定的事件目标(document对象)的顺序触发。
(2)捕获型事件(event capturing):事件从最不精确的对象(document 对象)开始触发,然后到最精确(也可以在窗口级别捕获事件,不过必须由开发人员特别指定)。
(3)DOM事件流:同时支持两种事件模型:捕获型事件和冒泡型事件,但是,捕获型事件先发生。两种事件流会触及DOM中的所有对象,从document对象开始,也在document对象结束。
捕获阶段、目标阶段、冒泡阶段。先调用捕获阶段的处理函数,其次调用目标阶段的处理函数,最后调用冒泡阶段的处理函数。
DOM事件模型最独特的性质是,文本节点也触发事件(在IE中不会)。
支持W3C标准的浏览器在添加事件时用addEventListener(event,fn,useCapture)方法,基中第3个参数useCapture是一个Boolean值,用来设置事件是在事件捕获时执行,还是事件冒泡时执行。而不兼容W3C的浏览器(IE)用attachEvent()方法,此方法没有相关设置,不过IE的事件模型默认是在事件冒泡时执行的,也就是在useCapture等于false的时候执行,所以把在处理事件时把useCapture设置为false是比较安全,也实现兼容浏览器的效果。
事件捕获阶段:事件从最上一级标签开始往下查找,直到捕获到事件目标(target)。
事件冒泡阶段:事件从事件目标(target)开始,往上冒泡直到页面的最上一级标签。
因为各种历史原因,事件的绑定在不同的浏览器总是有不同的写法,当然现在可能大多数人都已经习惯于jQuery的事件绑定,而不清楚javascript的原生事件绑定是什么样子。
链接:http://kb.cnblogs.com/page/199251/
Javascript绑定事件的方式
传统的事件绑定
element.onclick = function(e){}
<body> <input type="button" id="bt" name="bt button" value="this is a button"> <script> var bt = document.getElementById("bt"); bt.onclick = function(e){ alert("this is a alert"); alert(e.currentTarget.name); } </script> </body>
这是传统的事件绑定,它非常简单而且稳定,适应不同浏览器。e表示事件,this指向当前元素。但是这样的绑定只会在事件冒泡中运行,捕获不行。一个元素一次只能绑定一个事件函数。
W3C方式的事件绑定
W3C中推荐使用的事件绑定是用addEventListener()函数,element.addEventListener('click',function(e){...},false),上代码:
<body> <input type="button" id="bt" name="bt button" value="this is a button"> <script> var bt = document.getElementById("bt"); bt.addEventListener('click',function(e){ alert("this is a alert"); alert(e.currentTarget.name); },false); </script> </body>
如此的效果和之前的传统绑定方式是一样的,这种绑定同时支持捕获和冒泡,addEventListener()函数最后的参数表达了事件处理的阶段——false(冒泡),true(捕获)。这种方式最重要的好处就是对同一元素的同一个类型事件做绑定不会覆盖,会全部生效。比如对上面代码bt元素在进行一次click的绑定,那么两次绑定的事件处理函数都会执行,按照代码书写顺序。
但是IE浏览器不支持addEventListener()函数,只能在IE9以上(包括IE9)可以使用,IE浏览器相应的要使用attachEvent()函数代替。
IE下的事件绑定
IE下事件绑定的函数是attachEvent,它支持全系列的IE,但是如果你在Chrome等其他内核浏览器中使用这个函数去绑定事件,浏览器会报错的。
<body> <input type="button" id="bt" name="bt button" value="this is a button"> <script> var name = "world"; var bt = document.getElementById("bt"); bt.attachEvent('onclick',function(){ alert("hello "+ this.name); }); </script> </body>
attachEvent()函数支持事件捕获的冒泡阶段,同时它不会覆盖事件的绑定。但是一个缺点就是它处理函数中的this指向的是全局的window,所以上面代码弹出的结果会是"hello world"。
冒泡和捕获
上面的绑定事件中提到了冒泡和捕获阶段的概念,这两个概念对于理解事件是很重要的,对于它们的理解还要涉及到DOM(文档对象模型)和事件流的概念。事件流就是一个事件对象沿着特定数据结构传播的这么一个过程。
所谓的事件对象就是Event,当一个元素上绑定的事件被触发时会产生一个事件对象,从一切皆对象的观点看这是很符合逻辑的。冒泡和捕获讲的就是事件流在DOM中两种不同的传播方式。
<body>
<div id="bt1" style="width:300px;height:300px;border:1px solid red" name="divbt1">
<div id="bt2" style="width:100px;height:100px;border:1px solid red" name="divbt2"></div>
</div>
<script>
var bt1 = document.getElementById("bt1");
bt1.addEventListener('click',function(e){
alert("bt1"); //结果是bt1
},true);
var bt2 = document.getElementById("bt2");
bt2.addEventListener('click',function(e){
alert("bt2"); //结果是bt2 bt1
},true);
//bt1是true,当bt2是false, 点击bt2结果是bt1 bt2
//当bt1是false,bt2是true,点击bt2结果是bt2 bt1
//两个均是false,点击bt2结果是bt2 bt1 冒泡
//两个均是true,,点击bt2结果是bt1 bt2 捕获
</script>
</body>
<script>
window.onload = function(){
var outA = document.getElementById("outA");
var outB = document.getElementById("outB");
var outC = document.getElementById("outC");
// 目标(自身触发事件,是冒泡还是捕获无所谓)
outC.addEventListener('click',function(){alert("target");},true);
// 事件冒泡
outA.addEventListener('click',function(){alert("bubble1");},false);
outB.addEventListener('click',function(){alert("bubble2");},false);
// 事件捕获
outA.addEventListener('click',function(){alert("capture1");},true);
outB.addEventListener('click',function(){alert("capture2");},true);
};
</script>
<body>
<div id="outA" style="width:400px; height:400px; background:#CDC9C9;position:relative;">
<div id="outB" style="height:200; background:#0000ff;top:100px;position:relative;">
<div id="outC" style="height:100px; background:#FFB90F;top:50px;position:relative;"></div>
</div>
</div>
</body>
点击outC,弹出capture1 capture2 target bubble1 bubble2