Question

In case I need to attach multiple events to the same element using jQuery .on(), should I combine all events into one call and differentiate them using event.type? or should I have a separate .on() call for each event?

Combined events:

$('#main').on('mouseenter mouseleave click', '.myElement', function(event) {
    if (event.type == 'click') {
       return false;

    } else if (event.type == 'mouseenter') {
        $(this).addClass('active');

    } else if (event.type == 'mouseleave') {
        $(this).removeClass('active');
    }
}

Separate events:

$('#main').on('click', '.myElement', function(event) {
   return false;
}

$('#main').on('mouseenter', '.myElement', function(event) {
    $(this).addClass('active');
}

$('#main').on('mouseleave', '.myElement', function(event) {
    $(this).removeClass('active');
}

Which one is the fastest?

[Edit] Additional details: Obviously we need to consider two aspects, the first one is when the page has finished loading and those events handlers are being set, which will obviously be faster using only one .on() call. However the second aspect is when those events will actually be triggered, when mousing-over or clicking .myElement which I believe is more important as it will occur many times, while the .on() calls will be called only once (or more if the DOM changes, but still less than the events themselves).

Was it helpful?

Solution

You must distinguish between binding events (attaching a callback to an event), and between actually processing the triggered events (calling/executing the callback). The first might occur only once per page, while the later might occur hundred of times depending on the user activity.

  • If you consider the event-binding only – which occurs on document ready (eventually) and each time the DOM changes (e.g. on Ajax Complete) – then using only one .on() call with only one callback is faster: http://jsperf.com/multiple-jquery-events/2

  • If you consider the processing of the events being triggered – (i.e. the user clicks or mouse-overs .myElement) – then combining all events into one callback and differentiating them with if statements is also faster than having multiple callbacks: http://jsperf.com/multiple-jquery-events/4

Here are some combined results from both tests:

The fastest to bind and also the fastest to process events:

$('#main').on('mouseenter mouseleave click', '.myElement', function(event) {

    // Processing of the triggered event:
    if (event.type == 'click') {
        return false;

    } else if (event.type == 'mouseenter') {
        $(this).addClass('active');

    } else if (event.type == 'mouseleave') {
        $(this).removeClass('active');
    }
});

The above code is the recommended syntax. The following examples are for information only.


About 30% slower to bind, and 50% slower to process the events:

$('#main').on('click', '.myElement', function(event) {
    return false;
});

$('#main').on('mouseenter', '.myElement', function(event) {
    $(this).addClass('active');
});

$('#main').on('mouseleave', '.myElement', function(event) {
    $(this).removeClass('active');
});

The slowest to bind, and 70% slower to process the events:

$('#main').on({
    mouseenter: function() {
        $(this).addClass('active');
    },
    mouseleave: function() {
        $(this).removeClass('active');
    },
    click: function() {
        return false;
    }
}, '.myElement');

About 25% slower to bind, and the slowest to process the events:

$('#main').on('click', '.myElement', function(event) {
    return false;
});

$('#main').on('hover', '.myElement', function(event) {
    $(this).addClass('active');
}, function() {
    $(this).removeClass('active');
});

About 20% slower to bind, and 60% slower to process the events:

$('#main').on('click', '.myElement', function(event) {
    return false;

}).on('mouseenter', '.myElement', function(event) {
    $(this).addClass('active');

}).on('mouseleave', '.myElement', function(event) {
    $(this).removeClass('active');
});

OTHER TIPS

I think the combined events will work fast then seperated. Because when using combined jquery.on() called once in the jquery library, then it will call it internally. If it is called seperately then every time it needs to call the jquery library. If you see the code then you will find,

 on: function( types, selector, data, fn, /*INTERNAL*/ one ) {
    var type, origFn;

    // Types can be a map of types/handlers
    if ( typeof types === "object" ) {
        // ( types-Object, selector, data )
        if ( typeof selector !== "string" ) {
            // ( types-Object, data )
            data = data || selector;
            selector = undefined;
        }
             /* here is looping if in case combined event then this
                loop will work and all your events will bound here */
             /* in case of seperated events
                loop will work only for selected event and it will bind*/
        for ( type in types ) {
            this.on( type, selector, data, types[ type ], one );
        }
        return this;
    }

It is more easy if you use combined events like,

$('#main').on({
    mouseenter: function() {
        $(this).addClass('active');
    },
    mouseleave: function() {
        $(this).removeClass('active');
    },
    click: function() {
        return false;
    }
}, '.myElement');

As expected, the one with only one selector is the fastest. See the test results here for yourself:

http://jsperf.com/multiple-jquery-events

I also added a few other code snippets that do the same thing. This code is the best to use:

$('#main').on('mouseenter mouseleave click', '.myElement', function(event) {
    if (event.type == 'click') {
        return false;
    } else if (event.type == 'mouseenter') {
        $(this).addClass('active');
    } else if (event.type == 'mouseleave') {
        $(this).removeClass('active');
    }
});

However the second (case-switch) and last (no on()) are almost as fast

$('#main .myElement').click(function(event) {
    return false;
}).mouseenter(function(event) {
    $(this).addClass('active');
}).mouseleave(function(event) {
    $(this).removeClass('active');
});
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top