从经典事件管理转到J​​avaScript OOP中的事件委托 [英] Moving from classic event management to event delegation in JavaScript OOP

查看:95
本文介绍了从经典事件管理转到J​​avaScript OOP中的事件委托的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

旧的事件管理,其中特定操作的每个处理程序直接附加到目标元素,因为关于性能和内存节省的考虑在开发人员社区中开始传播。

The old event management in which each handler for specific actions was directly attached to the target element is becoming outdated, since considerations about performance and memory saving started spreading in the developers community.

事件委托实现有一个加速,因为jQuery更新了旧的 .bind() .live()方法与新的 .on()方法允许委派。

Event delegation implementations had an acceleration since jQuery updated the old fashioned .bind() and .live() methods with the new .on() method to allow delegation.

这决定了一些经验方法,在哪里使用事件委托,返工是必要的。
我试图制定一些最佳实践,同时保持我的库的编码风格,并寻找其他开发人员面临的类似情况找到答案。

This determines a change in some seasoned approaches, where to use event delegation a rework is necessary. I am trying to work out some best practice while keeping the coding style of my library, and looked for similar situations faced from other developers to find an answer.

使用OOP作为构造函数,我通常有这样的对象创建接口:

Using OOP with functions as constructors, I usually have interfaces for objects creation like this:

var widget = new Widget({
    timeout: 800,
    expander: '.expanders'
});

作为参数提供对象字面量,提供一个干净的传递的输入的名称和值的映射。这个代码的类可以是如下:

with object literals given as argument, providing a clean map of names and values of the input passed. The class underlying this code could be something like the following:

var Widget = function(options) {
    // some private members
    var _timeout;
    var _$widget;
    var _$expander;

    // methods
    this.init = function() {
        _timeout = options.timeout || 500;
        _$expander = $(options.expander);
        _$widget = _$expander.next();
        _$expander.on('click', _toggle);
    };
    var _toggle = function(e) {
        if (_$widget.is(':visible')) {
            _$widget.hide(_timeout);
        } else {
            _$widget.show(_timeout);
        }
    };
    this.init();
};

使用私有方法在代码可读性和清洁方面给了我一些好处(只有有用的方法公开暴露给用户),超出性能的小增益(每个范围分辨率比局部变量花费更多的时间)。但是,当谈到事件处理程序时,它与事件委托范例冲突。

Using "private" methods gave me some benefits in terms of code readability and cleanness (only useful methods are publicly exposed to the user), beyond the small gain in performance (each scope resolution takes more time than a local variable). But when speaking about event handlers, it clashes with the event delegation paradigm.

我想让公共的方法,我曾经在内部与类中的侦听器关联:

I thought to make public the methods that I used to associate internally to the listeners in the class:

    this.toggle = function(e) {
        if (_$widget.is(':visible')) {
            _$widget.hide(_timeout);
        } else {
            _$widget.show(_timeout);
        }
    };

然后在外部驱动,或在另一个代理类中,正确委派如下:

then driving externally, or in another proxy class, the proper delegation with something like this:

var widget = new Widget({
    expander: '.expanders'
});

$(delegationContext).on('click', '.expanders', widget.toggle);

但它似乎并不是我最好的方法,没有暴露的非有用的方法在界面中,所以我尝试了一种方式让主类直接知道所有的信息来自主委托事件,通过界面:

but it did not seem to me the best approach, failing in the exposure of a non-useful method in the interface, so I tried a way to let the main class know directly all the information to delegate the event autonomously, through the interface:

var widget = new Widget({
    timeout: 800,
    expander: {
        delegationContext: '.widgetContainer',
        selector: '.expanders'
    }
});

这将允许在类中内部使用私有方法:

which would allow to keep on using private methods internally in the class:

var $context = $(options.expander.delegationContext);
$context.on('click', options.expander.selector, _toggle);

您的实践和建议是什么?

What are your practice and suggestions about it?
And what are the main trends of other developers you heard about as far as today?

推荐答案


它与事件发生冲突

it clashes with the event delegation paradigm.

忘记那种模式!不要选择它,因为它酷,并直接附加事件已过时,只有在必要时选择它。事件委托不是不需要,也不会加速任何事情。这不是你可以应用的解决方案 - 你没有问题!

Forget that paradigm! Don't choose it because it's "cool" and directly attaching events "is becoming outdated", choose it only when it is necessary. Event delegation is not necessary for you, nor does it speed up anything. It is not a solution you can apply - you have no problem!

你有一个元素和单个元素特定的事件处理函数(每个小部件扩展器都有自己的函数)。您可以从您的问题中推断应用事件委派,您不能也不应该在这里使用它。

You have one element and a single element-specific event handler function (every widget expander has its own function). You can already infer from your problems applying event delegation that you cannot and should not use it here. Attach the handlers directly.

事件委托仅在有大量相似元素时才有用,这些元素在DOM中具有一个共同的祖先,附加相同的事件处理函数。您的 Widget 构造函数并不支持实例特定的选项,例如 expander 选择器。

Event delegation is only useful when you have a vast amount of similar elements, located consistently in the DOM with one common ancestor, that would all going to be attached the same event handler function. This is not the case with your Widget constructor that does take instance-specific options such as the expander selector.

在当前的 Widget 类中,使用事件委托会与单一责任原则。在事件委托范例中,你需要看到代理上下文中的元素作为一个整体,尽可能同质。

In your current Widget class, using event delegation would clash with the single responsibility principle. In the event delegation paradigm, you would need to see the elements in the delegation context as a whole, being as homogeneous as possible. The more element-specific data and state you add, the more delegation advantages you are loosing.

如果你真的想在这里使用事件委托,我建议你使用

If you really want to use event delegation here, I would suggest something like

var Widgets = {
    init: function(delegationContext) {
        $(delegationContext).on("click", ".widget-expander", function(e) {
             $this = $(this);
             $this.next().toggle($this.data("widget-expander-timeout") || 500);
        });
    },
    activate: function(options) {
        $(options.expander)
         .addClass("widget-expander")
         .data("widget-expander-timeout", options.timeout);
    }
};

这里不使用构造函数。您只需初始化事件委托上下文,然后可以添加要由委托机制捕获的单个元素。所有数据都存储在元素上,可从事件处理程序访问。示例:

Here no constructors are used. You just initialise the event delegation context, and then you can add single elements to be captured by the delegation mechanism. All data is stored on the element, to be accessible from the event handler. Example:

Widgets.init('.widgetContainer');
Widgets.activate({expander: '.expanders', timeout: 800});




您听说过的其他开发人员的主要趋势如今?

And what are the main trends of other developers you heard about as far as today?

除了这个问题是StackOverflow上的主题,我只能建议你不要跟随任何人所听到的趋势。了解新的(或广告或花哨的)技术,是的,但不要忘记了解何时使用它们。

Apart from that question being off-topic on StackOverflow, I can only advise you not to follow every trend someone heard about. Learn about new (or advertised or fancy) technologies, yes, but do not forget to learn about when to use them.

这篇关于从经典事件管理转到J​​avaScript OOP中的事件委托的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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