`

Event delegation in JavaScript

阅读更多

Event delegation in JavaScript

Tags: Delegation , DOM , Events , JavaScript , Performance

Last week, I spoke at and attended the Velocity web performance conference in San Jose. It was a lot of fun and I learned a lot in the other sessions I sat in on. During one session, Steve Souders announced to everyone that I had covered event delegation in my chapter from his new book, Even Faster Web Sites . Unfortunately, Steve misspoke as that topic isn’t covered, so I’m going to fill in the gap with this post.

Traditional event handling

Event delegation is, quite simply, using a single event handler to manage a particular type of event for the entire page. This isn’t a new idea, but it is an important one to grasp for performance. Most of the time, you’ll see code like this in web applications:

document.getElementById("help-btn").onclick = function(event){
    openHelp();
};

document.getElementById("save-btn").onclick = function(event){
    saveDocument();
};

document.getElementById("undo-btn").onclick = function(event){
    undoChanges();
};
 

This traditional way of coding assigns an event handler to each element that is actionable. For web sites with only a small amount of interaction, this may be okay. Large web applications, however, can grind to a halt when there are too many event handlers. The problem here isn’t necessarily a speed issue but rather a memory issue. If there are hundreds of possible interactions, there will end up being hundreds of ties between DOM elements and your JavaScript code. The more memory required of your web application, the slower it will run in general. Event delegation helps by minimizing this issue.

Event bubbling and capturing

Event delegation would be possible if not for the flowing nature of events. Early on in web development, browser vendors had to answer a philosophical question: when you click an area on a web page, what element are you actually interacting with? The problem came with the definition of interaction. Clicking within the bounds of an element is somewhat ambiguous. After all, a click on any element is also within the bounds of other elements. Consider clicking on a button. You’re actually clicking within the bounds of the button element, within the bounds of the <body> element, and within the bounds of the <html> element (see figure below).

Clicks within rectangles on a web page

At the time of this problem, there were two dominant browsers: Netscape Navigator and Internet Explorer. Each decided to solve this problem in a different way. Netscape defined an approach called event capturing, where events first occur on the highest object in the DOM tree (document) and then work down to the deepest element affected by the event. So in this example, event capturing has the click event first handled by document , then the <html> element, then <body> , and finally the <button> element.

Internet Explorer approached the problem in the exact opposite way. The IE team defined an approach called event bubbling. Event bubbling said that the deepest element affected by the event should receive the event first, then its parent should receive the event, and then it’s parent, etc., until the document object finally receives the event. Even though the document doesn’t have a distinct visual representation separate from <html> , it is still deemed to be its parent and thus bubbling continues up the DOM structure. The previous example would then see the <button> element receiving the event first, then <body> , <html> , and finally, document .

Diagram of event capturing and event bubbling

When defining the DOM, the W3C apparently found merit in both approaches and so the DOM Level 2 Events specification defines both event capturing and event bubbling as being present. First, the document receives the event, then the capturing phase commences to the most specific element affected by the event. Once the event is handled by that element, it bubbles back up to the document . The DOM addEventListener() method accepts three arguments: the name of the event to handle, a function to execute as the handler, and a Boolean set to true to handle the event during the capturing phase or false to handle during the bubbling phase. Most web developers have always been told to provide false as this argument so that it behaves the same way as attachEvent() in IE. Example:

//bubbling phase handler
document.addEventListener("click", handleClick, false);

//capturing phase handler
document.addEventListener("click", handleClick, true);
 

Attaching an event handler via a property (element.onclick = function(){} ), automatically assumes you want to use the bubbling phase to handle the event (this is done for backwards compatibility). Pretty much every browser except Internet Explorer (even through version 8.0) supports the DOM Level 2 events specification and therefore supports both capturing and bubbling. Internet Explorer still has its own proprietary event system that supports just bubbling.

Event delegation using bubbling

The key to event delegation is to use the bubbling aspect of events to handle them at the highest level (usually document ). Not all events bubble, but mouse and keyboard events do, and fortunately, those are the ones you’re in which you’re interested. Revisiting the earlier example, you can handle all of the click events by assigning an event handler to the document and then checking the event’s target to determine the course of action.

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?
    }
};
 

Using event delegation, the number of functions necessary to manage events has been cut back to one. All click events are now handled by a single function which then delegates to the appropriate function depending on the target of the event. The same can be down for mousedown , mouseup , mousemove , mouseover , mouseout , dblclick , keyup , keydown , and keypress . A word of caution, though, mouseover and mouseout are difficult to handle via event delegation due to their nature (the mouse is considered “out” when it moves from a container to its child).

Note: You can also accomplish event delegation via event capturing, but it only works in browsers that support capturing and therefore not in Internet Explorer.

Benefits

Event delegation has several benefits to the performance of a web application:

  1. Fewer functions to manage.
  2. Takes up less memory.
  3. Fewer ties between your code and the DOM.
  4. Don’t need to worry about removing event handlers when changing the DOM via innerHTML .

Moving from traditional event handling to event delegation has improved the overall performance of large-scale web applications around the world. It’s become so important that JavaScript libraries such as YUI and jQuery have started to bake it into their core interfaces. It really takes very little effort to implement event delegation, but the performance gains can be quite noticeable through the user interface. This is especially apparent when you move from dozens of event handlers to just one. Give event delegation a try and you may just never do traditional event handling again.

[转自 :http://www.nczonline.net/blog/2009/06/30/event-delegation-in-javascript/ ]

分享到:
评论

相关推荐

    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. **异步编程与事件...

    javascript 事件

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

    09JavaScript事件总结.docx

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

    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语法大全(程序员必备)

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

    前端开源库-eventy.zip

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

    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()`)以及自定义事件等,这些都极大地提高了...

Global site tag (gtag.js) - Google Analytics