1

我计划触发许多自定义 javascript 事件,并像这样监听它们

$(document).trigger('changeSettings',['param1value']);

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

我应该将这些on()事件绑定到除 之外的东西$(document)吗?将大量听众绑定到$(document)or是一种不好的做法$('body')吗?

4

3 回答 3

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

演示: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);

演示:http: //jsfiddle.net/Zv2W8/1/

于 2013-08-17T06:14:43.690 回答
2

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

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

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

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

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

小提琴


这是一个使用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);
于 2013-08-17T06:07:25.603 回答
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

于 2013-08-17T06:22:34.557 回答