对象字面量和事件监听器,最佳实践?

7
假设我有一个对象,其中包含一些属性和方法:
var Form = {
    name: 'sign-up',

    show: function() {...},
    hide: function() {...},
    validate: function() {...},
    updateCurrency: function() {...},
    handleCheckBox: function() {...}
}

现在我想在表单中发生特定事件时调用不同的方法,例如:
$('#country-select').bind('change', function() {
    Form.updateCurrency();
});

$("input[type='checkbox']").bind('change', function() {
    Form.handleCheckBox();
});

我有很多这样的事件监听器,坦率地说,我觉得它们一个接一个地列出来很丑陋,并且没有直接与它们相关的对象绑定。在我的对象文字 Form 中是否有一种更优雅的方式来封装它们?是否有最佳实践?

3个回答

6
我喜欢@gillesc的答案,它是正确的方向。然而,我认为我们可以做得更好。
@gillesc的答案的主要问题在于缺少动态方面的内容(例如事件处理程序),还强制你定义丑陋的回调函数。
所以这里是我认为你应该解决问题的方法。
// Test object
var testObj = {
    // Our event handlers. 
    // Notice how we must only define the callback function name here. 
    // Not the function itself. The callback function must be defined in testObj.
    handlers: {
        '#form submit': 'onSubmit'
    },
    // Method that will register all handlers to some selector
    registerHandlers: function() {
        var that = this;
        // Go through the handlers list.
        $.each(this.handlers, function(k, v) {
            // Parsing the event to two different parts. 
            // 1. trigger event
            // 2. selector
            var split = k.split(" "),
                el = split[0],
                trigger = split[1];

            // Delegating the trigger to selector
            $(document).delegate(el, trigger, that[v]);
        });
    },
    // Our actual callback function
    onSubmit: function(evt) {
        evt.preventDefault();
        alert("submit");
    }
};

这一切是如何运作的?很简单!我们只需要调用testObj.registerHandlers()

JSFiddle演示


此方法的好处在于您不必强制在对象中拥有registerHandlers方法。我快速/草率地举了一个例子来说明我的意思。JSFiddle演示在这里 - Kirstein

3

优化您的标记,并为与事件处理程序方法匹配的元素添加类,以便您可以轻松创建处理程序列表并迭代它们以将其绑定到目标元素。

Var Form = {
    ....,
    handlers: {
        country: function() {},
        checkbox: function() {}
    }
};

$.each(FORMS.handlers, function(k, v) {
    $('.' + k).on('change', v);
});


<select class="country">....</select>
<input class="checkbox" type="checkbox" />

然后,您只需添加类和处理程序以扩展。

这非常适合通用处理程序(通过类名附加事件)。 - Lee Kowalkowski

0

首先,你不需要在更多的函数中包装你的函数。 你不能只:

$('#country-select').bind('change', Form.updateCurrency);
$("input[type='checkbox']").bind('change', Form.handleCheckBox);

是的,但这忽略了我在回调函数中可能执行的其他操作,比如preventDefault()。它也不能帮助我像我想要的那样将事件处理程序封装在对象内部。 - alnafie
如果您使用bind方法包装事件处理程序,那么您可以在这种情况下使用它(并且您的绑定方法包装了事件处理程序)。否则(就像您问题中的示例一样),您将失去对事件的引用,那么handleCheckBox如何处理您的复选框呢? - Lee Kowalkowski

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接