Event delegation in JavaScript
作者:Nicholas C. Zakas
著作:《Javascript高级程序设计》,《ajax实战》
原文链接:http://www.nczonline.net/blog/2009/06/30/event-delegation-in-javascript/
传统的事件句柄
事件委托的实现十分简单,使用一个单独的事件句柄去管理整个页面特殊类别的事件。这不是一个新的想法,(原文:but it is an important one to grasp for performance) 。许多时候,你看得的都像下面的web应用的代码
document.getElementById("help-btn").onclick = function(event){
openHelp();
};
document.getElementById("save-btn").onclick = function(event){
saveDocument();
};
document.getElementById("undo-btn").onclick = function(event){
undoChanges();
};
传统的编码方式需要为每个元素事件句柄如果网站程序交互比较少这是OK的,但是大型web应用,尽管定义大量的事件句柄并没有太大的影响,麻烦的并不一定是速度的问题也是内存占用的问题。如果成百上千的程序交互最终将处理大量DOM元素之间的关系和编写大量的javascript代码,这就要求更多的内存来支持你的web应用,通常程序也会运行的很慢,事件委托帮助你解决这个难题。
事件的冒泡与捕获
如果不是动态绑定事件,事件委托是可能的。早期的web开发,浏览器供应商都会面临一个严肃的问题,就是当你点击网页中一个区域 什么元素是你实际想要触发的。这个问题伴随着页面元素交互的定义问题,点击任意一个元素的内部边界是模糊的。
点击一个按钮看看,你实际点击在一个按钮元素的内部,也是body元素内部,还是html元素的内部。
当这个问题出现的时候,有两个主要的浏览器:Netscape和IE。他们各自决定以不同的方式解决这个问题。网景公司定义的方法称为事件捕捉,一旦事件触发最先影响到DOM树最顶层对象(document),然后一直影响到事件源。因此,在这个例子中,单击事件的事件捕获最早由document处理,然后在<HTML>元素,然后是<body>,最后是<button>元素。
在IE中处理方式正好相反。 IE团队定义了一个方法称为事件冒泡。事件冒泡说的是,事件源元素的事件应该第一个被触发,那么它的父元素应该接收事件,然后它的父元素的父元素,等等,直到最后document对象接收事件。虽然document没有一个独特的视觉表现从<html>分开,但仍然被认为是<html>的父元素,从而继续冒泡DOM结构顶端。前面的例子可以看<button>首先接收到事件,然后就到<body>,再后到<html>,最后到达document对象。
当定义DOM标准时,W3C组织显然发现了事件的捕获机制与冒泡机制的优点,因而在DOM 2事件制定中支持这两种机制。首先,document对象接收一个事件,然后在捕获期间找到最具体的事件影响的元素,一旦这个元素绑定这个事件,事件将以冒泡的形式返回到document对象。DOM addEventListener() 函数接受三个参数,分别是事件名、事件句柄、支持事件冒泡还是捕获机制布尔值,绝大部分的web开发者会把这个最后那个参数设置为false,以期在IE中能有attachEvent()函数一样功能。
//bubbling phase handler
document.addEventListener("click", handleClick, false);
//capturing phase handler
document.addEventListener("click", handleClick, true);
通过一个附加属性来进行事件与事件句柄绑定(element.onclick = function(){}),事件将被自动作为冒泡机制来处理(这是为了向后兼容),几乎每一款浏览器除了IE(即便是IE8)都支持DOM 2事件处理捕获与冒泡机制,而IE仍然只支持冒泡。
在冒泡机制中使用事件委托
事件委托在关键在于使用冒泡处理最顶层元素(通常是document对象),并非所有的事件都会冒泡,但是但鼠标和键盘事件会,也是也我们感兴趣的事件。回顾早先的事例,你可以为document对象绑定一个click事件,然后判断事件源,根据事件源不同来执行不同函数。
document.onclick = function(event){
//IE doesn't pass in the event object
event = event || window.event;
//IE uses srcElement as the target
var target = event.target || event.srcElement;
switch(target.id){
case "help-btn":
openHelp();
break;
case "save-btn":
saveDocument();
break;
case "undo-btn":
undoChanges();
break;
//others?
}
};
使用事件委托,可以把众多的事件处理缩减到一个,当前所有click事件都被一个根据事件源不同进行不同操作的函数处理,你还可以以同样的方式创建mousedown, mouseup, mousemove, mouseover, mouseout, dblclick, keyup, keydown, keypress事件处理程序。还有一句忠告,mouseover、mouseout因为它们的特性决定了他们通过事件委托很难处理。
注:你也可以使用事件捕获机制来建立事件委托,但是它将不能在IE浏览器中运行。
好处:
1,更少的函数管理
2,使用更少内存
3,更少的DOM处理Javascript代码
4,改变DOM元素的innerHTML时不必担心事件绑定被删除
从传统的事件处理转移到事件委托改善了世界各地大型web应用的性能。这项目工作十分重要,YUI与JQuery 已经把事件委托提炼为核心接口。只要花很小的代价实现事件委托,但性能有十分明显的提升。当你把几十个事件处理转化为一个事件处理程序好处显尔益见。进行事件委托的尝试吧,或许你将再也不会使用传统的事件处理方式了。
分享到:
相关推荐
JavaScript_面試_事件傳遞機制和事件委託_Event_Propagation_&_Event_Delegation_-
前端项目-gator,Event delegation in javascript
Understand the important concepts of OOP in JavaScript, such as scope, objects, inheritance, event delegation, and more Find out how the module design pattern is used in OOP in JavaScript Design and ...
This book is for anyone with a foundation in JavaScript who wants to build web applications. Flight is quick and easy to learn, built on technologies you already understand such as the DOM, events, ...
在javasript中,代理、委托经常出现。 那么它究竟在什么样的情况下使用?它的原理又是什么? 这里介绍一下javascript delegate的用法和原理...这个例子主要取自David Walsh的相关文章(How JavaScript Event Delegation
如今的JavaScript技术界里最火热的一项技术应该是‘事件委托(event delegation)’了。使用事件委托技术能让你避免对特定的每个节点添加事件监听器;相反,事件监听器是被添加到它们的父元素上。事件监听器会分析从子...
1.我们通过 事件代理(event delegation) 让事件监听更高效, 2.我们利用 函数降频技术(function debouncing) 来限制一段时间内给定方法被调用的次数,请参考:如何防止事件函数的高频触发(中文翻译) 3.我们使用 ...
在需要为较多的元素绑定事件时应该使用事件委托 event delegation javascript事件传播 html如下: <body> <tr><td id=targetTd></td><td></td><td></td></tr> <tr><td></td><td></td><td></td></tr> </...
事件委托(event delegation):把若干个子节点上的相同事件的处理函数绑定到它的父节点上去,在父节点上统一处理从子节点冒泡上来的事件,这种技术就叫做事件委托。 补充一下:事件委托并不局限于父节点与子节点...
var events = require ( 'dom-delegation-stream' ) var values = require ( 'dom-value-stream' ) events ( document . body , 'input' , 'input[type=text]' ) . pipe ( values ( ) ) . pipe ( wherever ( ) ) ...
海市age楼-骨干脚手架图书馆 Mirage可让您从描述所涉及数据的单个JSON结构生成整个... selector: ".item", // optional, will be used in delegation callback: function(e) // will be bound to the click event
E是一个库,它将 eventBus/发射器、DOM 事件管理、委托事件和基于事件的实用程序组合到一个轻量级和高性能的库中。 E适用于所有主流浏览器和 IE11。 默认情况下,它包括在 IE11 中工作所需的任何 polyfill。...