一般我们给一个元素添加事件,有两种方式
一个是0级DOM,直接在html中属性中添加各类事件
如
<html> <body> <div id="div1" onclick="fn1()">div1 <div id="div2">div2 <div id="div3">div3</div> </div> </div> </body> </html>
还可以在js中添加相应事件
<script> document.getElementById("div1").onclick = fn1; //处理函数是没有()的,不然传递的就是函数的结果 function fn1(){ alert("div1"); }
</script>
上面说的是两个比较常用的添加事件的方法,都是0级DOM事件
下面来看另外一种 :2级DOM事件
DOM2级事件流:
一个事件流包含三个阶段,事件捕获阶段,处于目标阶段和事件冒泡阶段。
随意触发一个事件,比如click或者mouseover,这个事件就会产生一个事件流,然后先从目标对象的外层传入,然后处于目标对象之上,最后又传到外层。
addEventListener(type,fn,bool) //第一个参数是事件类型如“click”,fn指的是处理的函数,bool表示输入一个布尔值,如果为true,则指定事件句柄将在事件传播的捕捉阶段用于捕捉事件。如果参数为false,则事件句柄就是常规的,当事件直接发生在对象上,或发生在元素子女上,又向上起泡到该元素上的时候,被触发。
attachEvent(type,fn) //type是一个事件类型,如“onclick” ,这个与上面的方法不同,它是有on的,fn也是只的是处理函数。
1 <!DOCTYPE html> 2 <html xmlns="http://www.w3.org/1999/xhtml"> 3 <head> 4 <title></title> 5 <style type="text/css"> 6 #div1{ 7 background:red; 8 } 9 #div2{ 10 background:blue; 11 } 12 #div3{ 13 background:green; 14 } 15 </style> 16 <script> 17 window.onload = function () { 18 var eventHandler = { //事件类 19 addEvent: function (element, type, fn) { //添加事件 20 if (element.addEventListener) { 21 element.addEventListener(type, fn, false) //true 先触发外部,在逐渐触发内部 ,false先触发内部,然后触发外部 22 } else if (element.detachEvent) { 23 element.attachEvent("on" + type, fn); 24 } else { 25 element["on" + type] = fn; 26 } 27 }, 28 removeEvent: function (element, type, fn) { //删除事件 29 if (element.removeEvenListener) { 30 element.removeEvenListener(type, fn, false); 31 } else if (element.detachEvent) { 32 element.detachEvent(type, fn); 33 } else { 34 element["on" + type] = null; 35 } 36 } 37 } 38 39 var div1 = document.getElementById("div1"); 40 var div2 = document.getElementById("div2"); 41 var div3 = document.getElementById("div3"); 42 eventHandler.addEvent(div1, "click", function () { alert("div1") }); 43 eventHandler.addEvent(div2, "click", function () { alert("div2") }); 44 eventHandler.addEvent(div3, "click", function () { alert("div3") }); 45 } 46 </script> 47 </head> 48 <body> 49 <div id="div1">div1 50 <div id="div2">div2 51 <div id="div3">div3</div> 52 </div> 53 </div> 54 </body> 55 </html>
捕获阶段 在 div1 处检测是否有 useCapture 为 true 的事件处理程序,若有,则执行该程序,然后再同样地处理 div2。
目标阶段 在 div3 处,发现 div3 就是鼠标点击的节点,所以这里为目标阶段,若有事件处理程序,则执行该程序,这里不论 useCapture 为 true 还是 false。
冒泡阶段 在 div2 处检测是否有 useCapture 为 false 的事件处理程序,若有,则执行该程序,然后再同样地处理 div1。
addEventListener-事件流
当一个事件发生时,分为三个阶段:
捕获阶段 从根节点开始顺序而下,检测每个节点是否注册了事件处理程序。如果注册了事件处理程序,并且 useCapture 为 true,则调用该事件处理程序。(IE 中无此阶段。)
目标阶段 触发在目标对象本身注册的事件处理程序,也称正常事件派发阶段。
冒泡阶段 从目标节点到根节点,检测每个节点是否注册了事件处理程序,如果注册了事件处理程序,并且 useCapture 为 false,则调用该事件处理程序。
关于参数3 userCaoture,
- true 的触发顺序总是在 false 之前;
- 如果多个均为 true,则外层的触发先于内层;
- 如果多个均为 false,则内层的触发先于外层。
之前我们0级DOM上面,一个事件只能绑定一个函数,用2级DOM则可以添加多个处理函数。
<script> var div1 = document.getElementById("div1"); div1.addEventListener("click", fn1, false); div1.addEventListener("click", fn2, false); //添加2个处理函数,fn1,fn2 ,而0级DOM是不可以的 </script>
2级DOM事件优点:
可以对同一物件的同一事件绑定多个事件处理程序。
可以通过事件流三个阶段更好地控制何时触发事件处理程序。
工作于 DOM 元素,而不仅是 HTML 元素。