最有效的方式来动态绑定事件处理程序 [英] Most efficient way to dynamically bind event handlers

查看:80
本文介绍了最有效的方式来动态绑定事件处理程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问题:我需要将任意数量的事件处理程序绑定到任意数量的元素(DOM节点, window , document ),我需要能够在页面生命周期中更新动态创建(或销毁)节点的事件绑定。有三个选项可以解决这个问题:



I)窗口上的事件委托

II)每个节点上的直接事件绑定

III)共同祖先的事件代理(直到运行时才会知道,并且可能需要在DOM改变时重新计算)



做这件事最有效的方法是什么?

一点上下文



我正在处理一组需要对用户事件(点击,滚动等)进行分析跟踪的页面,我希望能够在一堆页面中轻松配置这些事件处理程序,而无需编写脚本来处理每个实例的事件绑定。此外,因为我可能需要在将来跟踪新事件,或者跟踪动态添加到页面或从页面中移除的元素上的事件,所以我需要能够解释生命周期中发生的DOM变化



作为我目前正在考虑的一个例子,我想创建一个接受配置对象的函数,该配置对象允许程序员指定默认处理程序对于每个事件,并允许它们覆盖特定元素:

  Analytics.init({
// default每个事件类型的处理程序
defaultHandlers:{
click:function(e){...},
focus:function(e){...}
},

//用于监听
的元素targetElements:{

//它应该适用于非DOM节点,如'window'和'document'
窗口:{
//默认处理程序应该被称为
的事件useDefaultHandlers:['click'],

//定制处理程序
scroll:function(e){...}
},

//它应该使用CSS选择器
#someId:{
useDefaultHandlers:['click','focus'],
blur:function(e){.. 。}
}
}
});



来源




解决方案因为:


    li>它表示页面上的< html> 元素,包含所有用户可以与之交互的HTML标记
  1. 它可用于JavaScript开始执行的时刻,否则无需窗口加载或DOM读取y事件处理程序
  2. 您仍然可以捕获滚动事件

至于效率事件代表团越多,事件所需的时间就越多,但是我们正在谈论~1到2毫秒的时间差 - maybe 。用户感觉不到它。通常,处理DOM事件会引入性能损失,而不是事件从一个节点冒泡到另一个节点。



我发现以下事情会产生负面影响一般的JavaScript性能:


  1. 您在文档树中拥有的节点越多,浏览器操作它的时间就越多。

  2. 页面上的事件处理程序越多,JavaScript越慢,但您需要100个处理程序才能真正看到差异。

  3. ol>

    主要来说,#1影响最大。我认为在大多数情况下,尝试提高事件处理的性能提升是一个不成熟的优化。我看到优化事件处理代码的唯一情况是当你有一个事件每秒触发多次(例如滚动和鼠标移动事件)。事件委托的附加好处是,您不必清理将从文档树中分离出来的DOM节点上的事件处理程序,从而允许浏览器收集该内存。



    (来自以下评论)wvandell表示:


    事件委派的表现成本几乎没有与事件的实际冒泡有关......将许多选择器委派给单个父代时会导致性能下降。


    这是真的,但是让我们考虑一下感知的性能。委派很多点击事件对用户来说不会很明显。如果您委托像滚动 mousemove 这样的事件,每秒可以启动50次以上处理事件),那么用户可以感知性能问题。这反过来反驳了我对事件处理程序代码过早优化的争论。



    许多点击事件可以委托给一个共同的祖先,没有问题,例如 document.documentElement中。我会在那里委托一个鼠标移动事件吗? 它取决于还有哪些事情正在进行,以及该委托的mousemove事件是否足够响应。


    Problem: I need to bind any number of event handlers to any number of elements (DOM nodes, window, document) at dynamically runtime and I need to be able to update event binding for dynamically created (or destroyed) nodes during the lifetime of my page. There are three options that I can see for tackling this problem:

    I) Event delegation on window
    II) Direct event binding on each node
    III) Event delegation on common ancestors (which would be unknown until runtime and would potentially need to be recalculated when the DOM is altered)

    What is the most efficient way of doing this?

    A little context

    I am working on a set of pages that need analytics tracking for user events (clicks, scrolling, etc.) and I want to be able to easily configure these event handlers across a bunch of pages without needing to write a script to handle the event binding for each instance. Moreover, because I may have the need to track new events in the future, or to track events on elements that are dynamically added to/removed from the page, I need to be able to account for changes in the DOM that occur during the lifetime of the page.

    As an example of what I'm currently considering, I would like to create a function that accepts a config object that allows the programmer to specify default handlers for each event, and allow them to override them for specific elements:

    Analytics.init({
        // default handlers for each event type
        defaultHandlers: {
            "click": function(e) { ... },
            "focus": function(e) { ... }
        },
    
        // elements to listen to 
        targetElements: {
    
            // it should work with non-DOM nodes like 'window' and 'document'
            window: {
                // events for which the default handlers should be called
                useDefaultHandlers: ['click'],
    
                // custom handler
                "scroll": function(e) { ... }
            },
    
            // it should work with CSS selectors
            "#someId": {
                useDefaultHandlers: ['click', 'focus'],
                "blur": function(e) { ... }
            }
        }
    });
    

    Sources

    解决方案

    I usually delegate events on the document.documentElement object because:

    1. It represents the <html> element on the page, which holds everything which holds all the HTML tags the user can interact with.
    2. It is available for use the moment JavaScript starts executing, negating the need for a window load or DOM ready event handler
    3. You can still capture "scroll" events

    As for the efficiency of event delegation, the more nodes the event must bubble up the longer it takes, however we're talking ~1 to 2 ms of time difference -- maybe. It's imperceptible to the user. It's usually the processing of a DOM event that introduces a performance penalty, not the bubbling of the event from one node to another.

    I've found the following things negatively affect JavaScript performance in general:

    1. The more nodes you have in the document tree, the more time consuming it is for the browser to manipulate it.
    2. The greater the number of event handlers on the page the more JavaScript slows down, though you would need 100s of handlers to really see a difference.

    Mainly, #1 has the biggest impact. I think trying to eek out a performance boost in event handling is a premature optimization in most cases. The only case I see for optimizing event handling code is when you have an event that fires multiple times per second (e.g. "scroll" and "mousemove" events). The added benefit of event delegation is that you don't have to clean up event handlers on DOM nodes that will become detached from the document tree, allowing the browser to garbage collect that memory.

    (From the comments below) wvandell said:

    The performance costs of event delegation have little to do with the actual 'bubbling' of events ... there is a performance hit incurred when delegating many selectors to a single parent.

    This is true, however let's think about the perceived performance. Delegating many click events won't be noticeable to the user. If you delegate an event like scroll or mousemove, which can fire upwards of 50 times per second (leaving 20 ms to process the event) then the user can perceive a performance issue. This comes back to my argument against premature optimizations of event handler code.

    Many click events can be delegated with no problem on a common ancestor, such as document.documentElement. Would I delegate a "mousemove" event there? Maybe. It depends on what else is going on and if that delegated "mousemove" event feels responsive enough.

    这篇关于最有效的方式来动态绑定事件处理程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆