事件绑定/委托

 

首先要作的第一件事情就是要先搞清楚什么是事件委托/绑定,这个东西有什么用,有什么优势和缺点,这样才能更好的去了解学习相关的知识。html

那就先作第一件事,认识事件绑定,不过说这个以前得先了解一下DOM事件流。node

一、什么是事件流函数

事件流描述的是从页面中接收事件的顺序。但有意思的是,IE 和 Netscape 开发团队竟然提出了差
很少是彻底相反的事件流的概念。IE 的事件流是事件冒泡流,而 Netscape Communicator 的事件流是事
件捕获流。学习

a、IE中的事件流测试

IE 的事件流叫作事件冒泡(event bubbling),即事件开始时由最具体的元素(文档中嵌套层次最深
的那个节点)接收,而后逐级向上传播到较为不具体的节点(也能够说是由子到父或者说从下到上)。this

若是你单击了页面中的 <div> 元素,那么这个 click 事件会按照以下顺序传播:
(1) <div>
(2) <body>
(3) <html>
(4) documentspa

代码以下:设计

1 <!DOCTYPE html>
2 <html>
3 <head>
4 <title>Event Bubbling Example</title>
5 </head>
6 <body>
7 <div id="myDiv">Click Me</div>
8 </body>
9 </html>

b、Netscape提出的事件流3d

Netscape Communicator团队提出的另外一种事件流叫作事件捕获(event capturing)。事件捕获的思想
是不太具体的节点应该更早接收到事件,而最具体的节点应该最后接收到事件。事件捕获的用意在于在
事件到达预约目标以前捕获它。code

若是仍之前面的 HTML 页面做为演示事件捕获的例子,那么单击 <div>元素就会如下列顺序触发 click 事件。

(1)  document

(2) <html>
(3) <body>
(4) <div>

“DOM2级事件”规定的事件流包括三个阶段:事件捕获阶段、处于目标阶段和事件冒泡阶段。首
先发生的是事件捕获,为截获事件提供了机会。而后是实际的目标接收到事件。最后一个阶段是冒泡阶
段,能够在这个阶段对事件作出响应。

再贴一个很形象的图片:

 二、事件处理程序

a、HTML事件处理程序

某个元素支持的每种事件,均可以使用一个与相应事件处理程序同名的 HTML 特性来指定。

b、 DOM0 级事件处理程序

经过 JavaScript 指定事件处理程序的传统方式,就是将一个函数赋值给一个事件处理程序属性

c、DOM2 级事件处理程序

DOM2级事件定义了两个方法,用于处理指定和删除事件处理程序的操做: addEventListener()和 removeEventListener()

 

三、什么是事件委托/绑定

对“事件处理程序过多”问题的解决方案就是事件委托。事件委托利用了事件冒泡,只指定一个事
件处理程序,就能够管理某一类型的全部事件。例如, click 事件会一直冒泡到 document 层次。也就
是说,咱们能够为整个页面指定一个 onclick 事件处理程序,而没必要给每一个可单击的元素分别添加事
件处理程序。

那事件委托有什么用呢?

//1.事件未绑定第一个问题 事件覆盖问题
//没有加事件绑定时出现的问题

 <div style="height:100px; width:100px; background="red"; ">测试</div>
1
var box = document.getElementsByTagName('div')[0]; 2 box.onclick = function() { 3 alert(1); 4 }; 5 box.onclick = function() { 6 alert(2); 7 }; 8 box.onclick = function() { 9 alert(3); // 只有这一个会显示 前两个都会被覆盖掉 10 };

//有加事件绑定时

1 box.addEventListener("click", function() {
2         alert(1) //这里的每个都会显示出来
3     }, false)
4     box.addEventListener("click", function() {
5         alert(2) //这里的每个都会显示出来
6     }, false)
7     box.addEventListener("click", function() {
8         alert(3) //这里的每个都会显示出来
9     }, false)

//2.事件绑定第二个问题    相同函数屏蔽问题

1 box.addEventListener("click",fn, false)
2     box.addEventListener("click",fn, false)
3     function fn(){
4         alert(1)
5     }

//3.事件绑定第三个问题 传递this问题
//没有事件绑定时的this

 1 box.onclick = function() {
 2         fn();
 3     };
 4 
 5     function fn() {
 6         alert(this); //window  这里的this指的仍是window
 7     };
 8 
 9     //有事件绑定时的this
10     box.addEventListener('click', fn, false);
11 
12     function fn() {
13         alert(this); //div   this的值从上面传过来了
14     };

//4.事件绑定第三个问题      添加一个事件会被覆盖或者只执行一次

 1 box.onclick = function() {
 2         alert(100);
 3     };
 4     box.onclick = fn;
 5 
 6     function fn() {
 7         alert(200);
 8     };
 9 
10     box.addEventListener("click", function() {
11         alert(100);
12     }, false)
13     box.addEventListener("click", fn, false)
14 
15     function fn() {
16         alert(200);
17     };

//IE中 event对象的获取

1 box.onclick=function(ev){
2         alert(ev)  //传统方法IE没法经过参数获取ev
3     }
4     box.addEventListener("click",function(ev){
5         alert(ev)   //能够经过事件绑定来获取
6     })

最后就是兼容封装

 1 //兼容写法封装
 2     //添加事件绑定
 3     function addEvent(obj, event, fn, bool) { //obj对象  event:事件  fn绑定函数  bool:是否捕获
 4         if (obj.addEventListener) {
 5             obj.addEventListener(event, fn, bool);
 6         } else {
 7             obj.attachEvent('on' + event, fn)
 8         }
 9     }
10 
11     //删除事件绑定
12     function removeEvent(obj, event, fn, bool) { //obj对象  event:事件  fn绑定函数
13         if (obj.removeEventListener) {
14             obj.removeEventListener(event, fn, bool);
15         } else {
16             obj.detachEvent('on' + event, fn)
17         }
18     }

 

window.onload = function(){
  var oUl = document.getElementById("ul1");
  oUl.onclick = function(ev){
    var ev = ev || window.event;  //event兼容写法
    var target = ev.target || ev.srcElement;  //target兼容写法
    if(target.nodeName.toLowerCase() == 'li'){
         alert(target.innerHTML);
    }
  }
}

 

 

更加详细的去参考高级程序设计第13章

 

事件流

事件流

相关文章
相关标签/搜索