我计划触发许多自定义javascript事件,并像
一样收听它们$(document).trigger('changeSettings',['param1value']);
$(document).on('changeSettings',function(e,param1){
// do something
});
我应该将这些on()
事件绑定到$(document)
以外的其他事件吗?将大量听众绑定到$(document)
或$('body')
?
答案 0 :(得分: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);
答案 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);
答案 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