首页 > 代码库 > 事件代理

事件代理

我们知道在javascript中添加到页面上的事件处理程序的数量将会直接关系到页面的整体运行性能。每一个函数都是对象,都会占用内存,内存中的对象越多,性能就会越差;并且dom访问的次数就会越多,导致延迟页面的交互就绪时间。如何处理事件的绑定,提高性能也就变得很重要。对于“事件处理程序多多”并且有嵌套关系的情况,就应该用事件委托。举个例子:

<div class="wrap"><ul><li class="btn1">btn1</li><li class="btn2">btn2</li><li class="btn3">btn3</li><li class="btn4">btn4</li></ul><p class="click1">click1</p><p class="click2">click2</p></div>

 

如果这个里面的所有li点击打印出“按钮”加上一个数字;所有的p标签点击打印出“我是小P”;外框点击的时候打印出“我是外层的包裹”;甚至它被包含在这个页面中,页面中还有很多的数据上报的点。那么,这种情况下我们如果用惯用的绑定方式一个一个那就会像这样:

$(div.wrap).on(click,function(){    console.log(我是外层的包裹);});$(ul.wrap-ul li).on(click,function(){    var numArr = [,,,],          index = $(this).index();    console.log(按钮 + numArr[index]);});$(div.wrap p).on(click,function(){    console.log(我是小p)});            

 

这段代码中我们绑定了多少次事件呢?数一下7次,那就是7个对象占进了内存,访问了7次dom。按照这个计算下去,如果有一百个的话,估计那计算机就要嫌弃你笨了。。。
还有一个重点,如果在某些情况下事件有嵌套关系,并且执行时我们要求没有干扰,一般我们会在子元素上添加一个阻止事件冒泡,以防止触发他父级对象的事件,那这个时候,如果你恰巧碰到我的“甚至”,需要很多数据上报的点,那怎么办?不会一个一个在事件绑定里面去添加吧,那我们就的工作量就太大了吧。
这个时候我们就可以用事件代理,所谓事件的代理我的理解是把事件绑定到父元素上面,甚至是document上面,来监听子元素的事件,这里用到的就是事件的冒泡机制。我们在触发任何一个元素的时候他都会从目标元素开始往上冒泡,也就是说这个click事件会首先在div上面发生,然后到父元素,到body,到html(不含低版本的IE),再到document,高版本浏览器甚至会冒泡到window上。那我们就利用这一点来实现事件代理,绑定一次事件做N件事。
还是上面的那个例子,我们用另外的一种方式来实现:

$(div.wrap).on(click,function(event){    console.log(我是外层的包裹);    var tar = event.target,          tagname = tar.tagName,curIndex,content,          numArr = [,,,];    if(tagname == LI){ //如果点击的是li,弹出“按钮 + 数字”        curIndex = $(tar).index();        content = 按钮+numArr[curIndex];    }else if(tagname == P){        content = 我是小p;    }    console.log(content);});    

 

再看一下这个方法,我们绑定了多少次事件?一次,就一次,这就意味着我们仅仅存了一个对象进入内存,只查找了一次dom结构。并且我们不会担心阻止事件冒泡的事情,那在最后如果有很多数据上报的时候就自然不需要每个去添加,我们只需要在document上面一次添加事件,监听所有元素就ok了,那我们就只需要一个方法就可以解决所有的数据上报的地方。但是。。。。
凡事总没有1+1=2那么绝对,不是所有的事件绑定都是用事件代理会更好的,下面我们再来看一个例子:

<div class="header"></div><div class="center"><div class="box">box1</div></div><ul class="slider"><li></li><li></li><li></li><li></li></ul><div class="inter"></div><div class="table"></div><div class="footer"></div>

就上面的这个结构,如果我们要在点击box的时候打印一个“盒子”;点击slider的li的时候打印出“焦点图”加上索引;点击table的时候打印出“tab切换”。也就是说我们的结构中的某一些要做一些操作,但是不是嵌套关系,不一定在哪一级,也不是大部分都要绑定,这个时候如果我们用事件代理的话,就要监听document,而document下面有很多的元素,这就更适合于单独绑定,就像这样:

 

$(div.box).on(click,function(){    console.log(盒子);});$(ul.slider li).on(click,function(){    var index = $(this).index();    console.log(焦点图 + index);});$(div.table).on(click,function(){    console.log(tab切换);});

小菜鸟知道的还很少,以上只是自己的理解,如果有不对的地方或者更好的建议欢迎指教。