事件代理那些事
简单说说。
事件代理,顾名思义,就是把本应该是自己的事情来交给别人来帮你做,比如,你要卖房,你不可能一天到晚蹲在马路边见人就问要不要买房吧,这样不仅消耗能量,还效率低,在javascript中也是,如果需要绑定事件的元素多了,你如果为每一个都绑个事件的话,你受的了,浏览器也受不了,搞不好它就崩溃了,你就尴尬了,所以把事件代理到元素的父级上是个好方法。
怎么搞?
要了解它是怎么搞起的,首先要知道背后的秘密,事件代理的秘密很简单,那就是事件冒泡,事件冒泡大家肯定都知道,比如当你单击了一个元素,这个单击事件不会就在这个元素上就结束了,而是会一直沿着它 的父级一直往上传,直到html元素,所以如果某个父级也绑定了单击事件的话,就会同时触发两个事件,这在一般情况下是不好的,因为提倡各行其职嘛,这样这个世界才会和谐的向前发展,所以大多情况下我们都是会去阻止它,在我刚开始学习js的时候,我就很郁闷,事件冒泡这玩意有什么卵用呢,不仅没用还有麻烦,所以我很讨厌,但在我接触了事件代理后,我发现原来它是有作用的,作用还挺大,就这样我就对它黑转粉了。但仅仅这样还不够,你可以把子元素的事件都绑定到父元素上,但在具体发生的时候,你总得知道是发生在哪个子元素上吧,这样才能执行相应的操作,不然父元素不得直接懵逼了。
检测具体是哪个元素,后面再说。
有啥好处?
没有好处的事情谁做呢是不是,这又不是公益,对程序员来说多一事不如少一事,所以事件代理肯定是有好处的,那么好处究竟是什么呢,好吧,其实很简单,不仅减少代码,还给浏览器减负了,浏览器可是我们的大boss啊,没有它我们就失业了,好吧,其实我还没就业,所以善待浏览器就是善待我们自己。其实稍微举个例子就清楚了,如果一个父元素有一千个子元素,这一千个子元素每个都有绑定了事件,那你怎么办,难道为每个元素都来绑一个,我去,直接辞职不干啊,所以这时把它代理到父元素上,一切都完美了,牺牲一个父元素,成全千万子元素,名垂千古,永垂不朽。。。。
代码怎么敲?
说来说去说的再多说的再感人都没什么用,关键还是要用代码敲出来,这样浏览器才懂,不然不是对牛弹琴嘛。俗话说天才第一步,雀氏纸尿裤。那么事件代理第一步就是如何获取事件具体来自哪个子元素,代码奉上:
function getTarget(e){ var e=e || window.event; return e.srcElement || e.target; }
为什么都有一个||呢?没办法,谁让IE喜欢搞特殊呢,人在屋檐下,总得要低头,我们改变不了那就只能去兼容了,谁让还有人用IE呢,通过这个函数,就可以获取发生事件的目标元素。接下来就是调用它,不然要它有何用。
function dosomething(e) { var target = getTarget(e); if(target.className=='yourname') { // do anything you like } }
调用其实也很简单,关键就是要检测这个目标的与众不同之处,就像我们人一样,每个人都一个独一无二的身份证,通过这个就可以分辨一个人,事件代理也是如此,目标传过来,根据它的与众不同之处来分辨具体是哪个,然后再相应的执行不同的事情就行了。
凡事都有两面性。
需要创建的以及驻留在内存中的事件处理器少了,这样我们就提高了性能,并降低了崩溃的风险,这样浏览器happy了,我们也开心,用户也高兴,皆大欢喜有木有。
再者在DOM更新后无须重新绑定事件处理器了。如果你的页面是动态生成的,比如说通过Ajax,你不再需要在元素被载入或者卸载的时候来添加或者删除事件处理器了。
不是所有的事件都能冒泡的。blur、focus、load和unload不能像其它事件一样冒泡。事实上blur和focus可以用事件捕获而非事件冒泡的方法获得(在IE之外的其它浏览器中)。
在管理鼠标事件的时候有些需要注意的地方。如果你的代码处理mousemove事件的话你遇上性能瓶颈的风险可就大了,因为mousemove事件触发非常频繁。而mouseout则因为其怪异的表现而变得很难用事件代理来管理。
总结大会。
总的来说,事件冒泡还是很优秀的,我们要时刻想着它,需要用的时候就用,不要委屈自己,伤身体就不好了。