2013-06-21 2 views
3

В случае, если мне нужно приложить несколько событий к одному элементу с помощью JQuery .on(), я должен объединить все события в один вызов и дифференцировать их с помощью event.type? или должен ли я иметь отдельный вызов .on() для каждого события?JQuery: Лучший способ для обработки нескольких событий для лучшей производительности

Комбинированные события:

$('#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'); 
    } 
} 

Отдельные события:

$('#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'); 
} 

Какой самый быстрый?

[Редактировать] Дополнительная информация: Очевидно, что мы должны рассмотреть два аспекта, первый из них, когда завершения загрузки страницы и те события, обработчики Создаются, которые, очевидно, будет быстрее, используя только один .on() вызов. Однако второй аспект заключается в том, когда эти события будут фактически активированы, когда мышь или нажатие .myElement, которое, по моему мнению, более важно, поскольку оно будет происходить много раз, а вызовы .on() будут вызываться только один раз (или больше, если DOM изменяется, но все же меньше, чем сами события).

+1

[Протестируйте] (http://jsperf.com) – billyonecan

+1

Вы можете попробуйте сами: http://jsperf.com/. Если речь идет только о вызове '.on' несколько раз или нет, то, конечно, лучше просто называть его один раз. Вы можете передать объект в качестве аргумента, если хотите связать несколько разных обработчиков событий: http://api.jquery.com/on/#on-events-selector-data. Если вопрос заключается в том, что один или несколько обработчиков событий «быстрее» используют JSPerf. –

+0

Первый должен быть быстрее, поскольку он только один раз выбирает элемент '# main'. – Broxzier

ответ

4

Вы должны различать связывания событий (присоединение обратного вызова к событию), а между фактически обработка инициированных событий (вызов/выполнение обратного вызова). Первый может произойти только один раз на страницу, а позже - сотни раз в зависимости от активности пользователя.

  • Если вы считаете событие связывания только - что происходит на документ, готовый (в конце концов) и каждый раз, когда DOM изменяется (например,на Ajax Complete) - затем, используя только один .on() вызов только один обратный вызов быстрее: http://jsperf.com/multiple-jquery-events/2

  • Если вы считаете обработка событий, которые инициированы - (т.е. пользователь щелкает или мыши пуловеры .myElement) - тогда объединить все события в один обратный вызов и дифференцировать их с if заявлениями также быстрее, чем имеющие несколько обратных вызовов: http://jsperf.com/multiple-jquery-events/4

Вот некоторые комбинированные результаты обоих тестов:

Самый быстрый связывать и также быстро производить обработку событий:

$('#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'); 
    } 
}); 

Приведенный выше код является рекомендуемым синтаксис. Следующие примеры приведены только для информации.


Около 30% медленнее, чтобы связать, и 50% медленнее обрабатывать события:

$('#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'); 
}); 

Самый медленный связывать, и 70% медленнее обрабатывать события:

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

Около 25% медленнее связывать, а самый медленный - обрабатывать События:

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

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

О 20% медленнее связывающиеся, и 60% медленнее обрабатывать события:

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

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

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

Как и ожидалось, самый быстрый только один селектор. Смотрите результаты испытаний здесь для себя:

http://jsperf.com/multiple-jquery-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'); 
    } 
}); 

Однако второй (случай-переключатель) и последний (не on()) почти так же быстро

$('#main .myElement').click(function(event) { 
    return false; 
}).mouseenter(function(event) { 
    $(this).addClass('active'); 
}).mouseleave(function(event) { 
    $(this).removeClass('active'); 
}); 
+0

Думаю, что у вас может быть ложный позитив. jQuery только связывает событие один раз, а затем толкает в стек, чтобы добавить больше событий. Вот почему 'element.addEventListener' будет выглядеть медленнее, чем' jQuery.on' на jsperf.com. – andlrc

+1

Также 'no on()' использует '.on' внутренне. http://james.padolsey.com/jquery/#v=1.7.2&fn=jQuery.fn.click – andlrc

+0

Ваш второй подход не соответствует той же цели, что и синтаксис 2-селекторов (делегированные события). Во втором примере события добавляются в '.myElement', в то время как они должны быть добавлены в элемент' # main' вместо этого, чтобы позволить новым добавленным элементам '.myElement' (например, через ajax) также запускать событие. – Community

0

Я думаю, что combined события будут работать быстро, то seperated , Поскольку при использовании combinedjquery.on(), вызываемого один раз в jquery library, он будет называться внутренним. Если он называется seperately, то каждый раз ему нужно позвонить jquery library. Если вы видите код, то вы найдете,

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

Это более легко, если вы используете combined events как,

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

Это не имеет никакого смысла. Почему бы быстрее, когда jQuery называет себя внутренне, вы можете просто сделать: 'var $ ('# main'). On(). On(). On()' – andlrc