`
highzhu
  • 浏览: 10804 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
文章分类
社区版块
存档分类
最新评论

(翻译)Event delegation in JavaScript

阅读更多

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 已经把事件委托提炼为核心接口。只要花很小的代价实现事件委托,但性能有十分明显的提升。当你把几十个事件处理转化为一个事件处理程序好处显尔益见。进行事件委托的尝试吧,或许你将再也不会使用传统的事件处理方式了。










 

分享到:
评论
1 楼 firebaby 2010-07-26  
此文甚好,支持。

相关推荐

    JavaScript 面试:事件传递机制和事件委托 Event Propagation & Event Delegation - 彭彭直播 at 2020/03/31

    JavaScript_面試_事件傳遞機制和事件委託_Event_Propagation_&_Event_Delegation_-

    Modular Programming with JavaScript(PACKT,2016)

    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 ...

    JavaScript经典教程.rar

    JavaScript提供了丰富的事件类型,如`click`、`mouseover`、`keydown`等,并引入了事件监听器(event listeners)和事件委托(event delegation)等高级技术来高效地管理事件。 2. **对象**:JavaScript是一门面向...

    Event

    7. **事件委托(Event Delegation)**:为了高效地处理大量相似元素的事件,可以将事件监听器添加到这些元素的共同祖先上,然后通过事件对象的`target`属性判断真正触发事件的是哪个子元素。 8. **异步编程与事件...

    09JavaScript事件总结.docx

    五、事件委托(Delegation) 事件委托是一种优化技术,通过在共同的父元素上绑定事件监听器,而不是在每个子元素上单独绑定。当子元素事件触发时,事件冒泡到父元素,由父元素的监听器处理。这种方法减少了内存消耗...

    javascript 事件

    JavaScript事件还有其他高级特性,如事件委托(Event Delegation),它通过将事件监听器添加到父元素来处理子元素的事件,从而提高性能和代码可维护性。还有事件阻止(Event Stop)方法,如`event.stopPropagation()...

    JavaScript语法大全(程序员必备)

    3. **使用事件委托(Event Delegation)**:通过将事件处理器绑定到父元素上,而不是每个子元素,可以提高事件处理的效率。 ### 错误处理与调试 1. **异常处理(Exception Handling)**:使用try...catch语句来捕获并...

    前端开源库-eventy.zip

    此外,事件委托(event delegation)是一种优化性能的策略,它允许我们在父元素上设置一个事件监听器,而不是为每个子元素分别设置。如果`eventy`库支持事件委托,那么它可以简化代码并提高性能,尤其是当有大量动态...

    Getting Started with Twitter Flight

    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, ...

    JavaScript 45 道面试题及答案.docx

    JavaScript 事件代理(Event Delegation) ----------------------------- 事件代理(Event Delegation),又称之为事件委托。是 JavaScript 中常用绑定事件的常用技巧。顾名思义,“事件代理”即是把原本需要绑定...

    JavaScript判断按钮被点击的方法

    这样可以更方便地添加和管理多个事件监听器,同时它们通常还提供了一些高级功能,比如事件委托(event delegation)、事件冒泡控制(event bubble control)等。 此外,在学习和使用JavaScript进行事件处理时,我们...

    JavaScript实用技巧集锦

    11. **事件委托(Event Delegation)**:利用事件冒泡原理,通过在父元素上监听事件,处理子元素的事件,减少事件监听器的数量,提高性能。 12. **防抖(Debouncing)与节流(Throttling)**:用于优化性能,限制...

    javascript学习视频

    6. **事件委托(Event Delegation)**:这是一种高效的处理动态生成元素事件的方法。通过在父元素上设置一个事件监听器,然后根据事件的目标元素来决定是否执行相应的操作。 在"0-7课件及源码"中,你可能不仅会看到...

    JavaScript图文混排滑动切换效果.rar

    6. **优化性能**:为了确保在大量元素时仍能保持良好的性能,可以考虑使用事件代理(event delegation)减少事件监听器的数量,或者利用缓存策略避免频繁操作DOM。 7. **响应式设计**:为了适应不同设备和屏幕尺寸...

    javascript经典特效---固定的图片广告.rar

    例如,使用事件委托(event delegation)来处理多个相似元素的事件,或者延迟加载(lazy loading)广告图片,直到它们进入可视区域才开始加载。 总的来说,这个“javascript经典特效---固定的图片广告.rar”实例是...

    window对象--event对象详解

    此外,Window对象和Event对象也常常和其他JavaScript特性结合使用,比如事件委托(Event Delegation)、事件修饰符(如`event.preventDefault()`和`event.stopPropagation()`)以及自定义事件等,这些都极大地提高了...

    高性能JavaScript.pdf

    - 事件委托(Event Delegation)是一种提高事件处理效率的技术,通过监听父元素上的事件来处理子元素的事件,从而避免为每个子元素单独绑定事件监听器。 #### 四、算法与流程控制(Algorithms and Flow Control) ...

Global site tag (gtag.js) - Google Analytics