1

由于对性能和内存节省的考虑开始在开发人员社区中传播开来,因此特定操作的每个处理程序都直接附加到目标元素的旧事件管理正在变得过时。

自从 jQuery用新方法更新了旧的.bind()和方法以允许委托后,事件委托实现有了加速。.live().on()

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

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

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

将对象文字作为参数给出,提供传递的输入的名称和值的干净映射。此代码基础的类可能类似于以下内容:

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();
};

使用“私有”方法在代码可读性和清洁度方面给了我一些好处(只有有用的方法向用户公开),除了性能上的小幅提升(每个范围解析比局部变量花费更多时间)。但是当谈到事件处理程序时,它与事件委托范式发生冲突。

我想公开我用来在内部与班级中的听众相关联的方法:

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

然后在外部或另一个代理类中驱动适当的委托,如下所示:

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

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

但在我看来这不是最好的方法,在接口中暴露了一个无用的方法失败,所以我尝试了一种方法,让主类直接知道所有信息以自主委托事件,通过接口:

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

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

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

您对此有何做法和建议?
到目前为止,您听说的其他开发人员的主要趋势是什么?

4

1 回答 1

0

它与事件委托范式相冲突。

忘记那个范式!不要因为它“酷”而直接附加事件“已经过时”而选择它,仅在必要时选择它。事件委托对您来说不是必需的,也不会加速任何事情。这不是您可以应用的解决方案 - 您没有问题!

您有一个元素和一个特定于元素的事件处理函数(每个小部件扩展器都有自己的函数)。您已经可以从应用事件委托的问题中推断出您不能也不应该在此处使用它。直接附加处理程序。

事件委托仅在您拥有大量相似元素时才有用,这些元素始终位于具有一个共同祖先的 DOM 中,它们都将附加相同的事件处理函数。Widget对于使用特定于实例的选项(例如选择器)的构造函数,情况并非如此expander

在您当前的课程中,使用事件委托会与单一职责原则Widget发生冲突。在事件委托范式中,您需要将委托上下文中的元素视为一个整体,并尽可能同质化。您添加的特定于元素的数据和状态越多,您失去的委托优势就越多。

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

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

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

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

到目前为止,您听说的其他开发人员的主要趋势是什么?

除了这个问题在 StackOverflow 上是题外话之外,我只能建议你不要追随别人听说过的每一个趋势。了解新的(或宣传的或花哨的)技术,是的,但不要忘记了解何时使用它们。

于 2013-09-15T23:47:31.647 回答