How Expensive Is This jQuery Trigger?
This jsFiddle demonstrates what I'm talking about. Essentially, I'm binding some elements to a custom event and then calling a trigger using
$('*').trigger('myevent', args)
I'm doing this because I will have some elements bound to this event, but I don't know what t开发者_Python百科hey will be yet, and I'd like to decouple this code as much as possible. Is it ridiculously expensive to call $('*').trigger
or not that expensive since it will only trigger the elements that are bound to that event?
In other words, does this code go through every element on the page to see if it is attached to this event, or does it know which ones are and just triggers them? If the former is the case, is there a better solution?
The better solution is to bind and trigger events off of the document, since it will only be one DOM element:
$(document).bind('myevent', function(e) {});
$(document).trigger('myevent');
Now ultimately what sounds like an even better solution to your problem would be to use event delegation:
$(document).delegate('.my-delegation-selector', 'myevent', function(e) {
});
Take a look at this example from http://api.jquery.com/delegate/
<!DOCTYPE html>
<html>
<head>
<style>
p { color:red; }
span { color:blue; }
</style>
<script src="http://code.jquery.com/jquery-1.5.js"></script>
</head>
<body>
<p>Has an attached custom event.</p>
<button>Trigger custom event</button>
<span style="display:none;"></span>
<script>
$("body").delegate("p", "myCustomEvent", function(e, myName, myValue){
$(this).text("Hi there!");
$("span").stop().css("opacity", 1)
.text("myName = " + myName)
.fadeIn(30).fadeOut(1000);
});
$("button").click(function () {
$("p").trigger("myCustomEvent");
});
</script>
</body>
</html>
Have you thought of pubsub? Something as simple as.
(function() {
var $obj = $(window);
window.pub = function(ev, data) {
$obj.trigger(ev, data);
};
window.sub = function(ev, f) {
$obj.bind(ev, f);
};
})();
or drop the jQuery dependency
(function() {
var $obj = {},
undefined;
window.pub = function(ev, data) {
if ($obj[ev] === undefined) {
return false;
}
for (var i = 0, len = $obj[ev].length; i < len; i++) {
$obj[ev][i](data);
}
};
window.sub = function(ev, f) {
if ($obj[ev] === undefined) {
$obj[ev] = [];
}
$obj[ev].push(f);
};
})();
Both amplify.subscribe and Backbone.Events have specific objects for this. You may even find other libraries with similar objects. There are even libraries PubSub.js for this.
Example:
$("table.sort th").click(function(e) {
...
window.pub("click.sortHeader", e);
});
...
$.fn.pagify = function(json) {
var table = $(this);
...
//enter code here
window.sub("click.sortHeader", function() {
// handle table sorting.
// adjust table pagifying plugin accordingly.
});
};
In general pub
is trigger
and sub
is bind
. In this particular example we have two independent plugins. They don't know whether they are on the same page or talking at all. But since the sorting "breaks" the paging plugin on our table we have a subscription on the sorting "event" to fix our paging.
Someone else can come up with a better example. It's basically just a way of message passing without making any assumptions about whether either the message giver or receiver exists.
Looking at jquery source code. When you trigger an event on jQuery it check for a valid node
// don't do events on text and comment nodes
if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) {
return undefined;
}
And later check for a valid handler on the actual dom object
// Trigger the event, it is assumed that "handle" is a function
var handle = jQuery._data( elem, "handle" );
if ( handle ) {
handle.apply( elem, data );
}
I think that the real problem is the use of $('*') selector. Try another of the suggested solutions to your problem
精彩评论