什么是自定义操作绑定的最佳实践?

时间:2013-08-17 05:44:44

标签: javascript javascript-events

我计划触发许多自定义javascript事件,并像

一样收听它们
$(document).trigger('changeSettings',['param1value']);

$(document).on('changeSettings',function(e,param1){
    // do something
});

我应该将这些on()事件绑定到$(document)以外的其他事件吗?将大量听众绑定到$(document)$('body')

是不好的做法

3 个答案:

答案 0 :(得分:2)

虽然这样可行,但最好(从可读性和性能角度来看)使用专用事件库。如果您不想这样做,这是一种更简洁的方法。

jQuery允许创建documentFragments,它只是作为对象存在于内存中。它不会添加到您的页面中,只能使用返回的值(此处存储在window.events中)触发事件。

window.events = $('<div>');

events.on('changeSettings',function(e,param1){
    // do something
});

events.trigger('changeSettings', ['value']);

fiddle


以下是使用radio.js的示例,该示例执行事件而不执行任何操作。

radio('changeSettings').subscribe(function(data1, data2) {
    //do something with data1 and data2
});
radio('changeSettings').broadcast(data1, data2);

你也可以做这样的事情,它允许重构和缩小。

var events = {changeSettings: radio('changeSettings')};

events.changeSettings.subscribe(function(data1, data2) {
    //do something with data1 and data2
});
events.changeSettings.broadcast(data1, data2);

答案 1 :(得分:2)

我不知道它是否会“更好”,但以下内容不会与DOM交互 - 它会保留对非追加元素的引用并处理它。虽然如果jQuery内部对.trigger()做了更多的事情,我也不会感到惊讶。如果这些事件与DOM无关,那么请远离它:)这是一个例子:

var Events = (function () {
    "use strict";

    var trigger, events, onMethod, triggerMethod;

    trigger = $("<div>");
    events = {
        test1: 1,
        test2: 1
    };
    onMethod = function (eventName, func) {
        if (events[eventName]) {
            trigger.on(eventName, func);
        }
    };
    triggerMethod = function (eventName) {
        trigger.triggerHandler(eventName, Array.prototype.slice.call(arguments, 1));
    };

    return {
        on: onMethod,
        trigger: triggerMethod
    };
}());

Events.on("test2", function () {
    console.log(arguments);
});

Events.trigger("test2", [1, 2, 3], 3);

DEMO: http://jsfiddle.net/Kh4HC/

您可以删除events变量;这只是我定义什么是“允许”的方式。 jQuery完成的任何额外的事情,以及对jQuery的依赖都可以避免,并且可以制作一个小的触发库来完全避开DOM。或者,使用几个好的现有库之一就可以了。作为一种希望更好地帮助理解如何的方法,这可能在库中内部工作,这是一个例子:

var Events = (function () {
    "use strict";

    var events, onMethod, triggerMethod, slice;

    events = {};
    onMethod = function (eventName, func) {
        if (!(events[eventName])) {
            events[eventName] = [];
        }
        events[eventName].push(func);
    };
    triggerMethod = function (eventName) {
        var matchedEvent, args, i, j, cur;
        matchedEvent = events[eventName];
        if (matchedEvent) {
            args = slice(arguments, 1);
            for (i = 0, j = matchedEvent.length; i < j; i++) {
                cur = matchedEvent[i];
                cur.apply(null, args);
            }
        }
    };
    slice = function (arr, start, howMany) {
        var stop, newArr, i, j, cur;

        start = +start || 0;
        howMany = +howMany || Infinity;
        stop = Math.min(start + howMany, arr.length);
        newArr = [];
        for (i = start, j = stop; i < j; i++) {
            cur = arr[i];
            newArr.push(cur);
        }
        return newArr;
    };

    return {
        on: onMethod,
        trigger: triggerMethod
    };
}());

Events.on("ahh", function () {
    console.log("ahh", arguments);
});

Events.trigger("ahh", [1, 2, 3], 3);
Events.trigger("ahh", {a: "b"}, true);

DEMO: http://jsfiddle.net/Zv2W8/1/

答案 2 :(得分:1)

如果您的事件与DOM无关,那么在DOM元素上触发它们可能不是一个好习惯。您可以做的是(我注意到您使用的是jQuery)是使用新的jQuery对象作为事件总线。

例如:

var eventBus = $({});

//listen for the event
eventBus.on('changeSettings', function (e) {
    console.log('changeSettings triggered ', e.settings); 
});

//fire the event
var evt = $.Event('changeSettings');
evt.settings = { someSetting: 1 };

eventBus.trigger(evt);

但是,您不应该通过事件总线广播所有事件,只应针对应用程序的多个部分全局感兴趣的事件。例如,像'userInfosChanged'这样的事件可能对广播很有意思,因为很多应用程序的模块可能想要做出反应。另一方面,某些对象实例可能会触发其他不需要广播的事件,因此在这种情况下,您将在对象实例本身上注册事件处理程序。

如果我们回到DOM事件。我们在容器元素上使用侦听器的主要原因之一,如document或包含子元素触发事件的其他元素,是为了避免必须将事件处理程序附加到每个子节点,这在内存方面更有效。此外,当可以从容器中动态添加或删除子项时,这是一种非常有用的方法。

编辑:如果您正在寻找一些专门用于活动的小型图书馆,您可以咨询http://microjs.com/#event