Эффективность jQuery bind - PullRequest
16 голосов
/ 19 марта 2010

У меня проблема со скоростью загрузки с использованием нескольких привязок jQuery на пару тысяч элементов и входов, есть ли более эффективный способ сделать это?

На сайте есть возможность переключаться между списками товаров с помощью ajax-звонков, страница не может обновляться. В некоторых списках есть 10 элементов, около 100, некоторые более 2000. Проблема скорости возникает, когда я начинаю переключаться между списками; каждый раз при загрузке списка предметов 2000+ система тянет в течение примерно 10 секунд.

Перед тем, как перестроить список, я устанавливаю html целевого элемента в '' и освобождаю две привязки ниже. Я уверен, что это как-то связано со всеми родительскими, последующими и дочерними вызовами, которые я выполняю в обратных вызовах. Любая помощь очень ценится.

цикл 2500 раз

<ul>
  <li><input type="text" class="product-code" /></li>
  <li>PROD-CODE</li>
  ...
  <li>PRICE</li>
</ul>

конец цикла

$('li.product-code').bind( 'click', function(event){ 

    selector = '#p-'+ $(this).prev('li').children('input').attr('lm');

        $(selector).val(

            ( $(selector).val() == '' ? 1 : ( parseFloat( $(selector).val() ) + 1 ) )

        );

    Remote.Cart.lastProduct = selector;
    Remote.Cart.Products.Push( 

            Remote.Cart.customerKey, 
            { 
                code      : $(this).prev('li').children('input').attr('code'),
                title     : $(this).next('li').html(), 
                quantity  : $('#p-'+ $(this).prev('li').children('input').attr('lm') ).val(), 
                price     : $(this).prev('li').children('input').attr('price'),
                weight    : $(this).prev('li').children('input').attr('weight'),
                taxable   : $(this).prev('li').children('input').attr('taxable'),
                productId : $(this).prev('li').children('input').attr('productId'),
                links     : $(this).prev('li').children('input').attr('productLinks')
            },
            '#p-'+ $(this).prev('li').children('input').attr('lm'),
            false,
            ( parseFloat($(selector).val()) - 1 )

    );

    return false;

});

$('input.product-qty').bind( 'keyup', function(){ 

    Remote.Cart.lastProduct = '#p-'+ $(this).attr('lm');
    Remote.Cart.Products.Push( 

            Remote.Cart.customerKey, 
            { 
                code      : $(this).attr('code') , 
                title     : $(this).parent().next('li').next('li').html(), 
                quantity  : $(this).val(), 
                price     : $(this).attr('price'),
                weight    : $(this).attr('weight'),
                taxable   : $(this).attr('taxable'),
                productId : $(this).attr('productId'),
                links     : $(this).attr('productLinks')
            },
            '#p-'+ $(this).attr('lm'),
            false,
            previousValue
    );
});

Ответы [ 4 ]

28 голосов
/ 19 марта 2010

Вы связываете обработчик 2500 раз, вместо этого заставьте вашу функцию использовать либо live, либо делегирование следующим образом:

$('li.product-code').live('click', function(event){ 
$('input.product-qty').live('keyup', function(){ 

.live() прослушивает щелчок, чтобы всплыть на уровне DOM, затем выполняет событие в контексте источника клика. Это означает, что у вас есть один обработчик событий вместо 2500 из них, что означает, что он намного быстрее и проще в браузере.

Если у вас есть контейнер, который оборачивает замещенный контент, который не заменяется (остается во всех вызовах AJAX), вы можете сделать его более локальным, например:

$('#container').delegate('li.product-code', 'click', function(event){ 
$('#container').delegate('input.product-qty', 'keyup', function(){ 

Результатом этого является то, что событие вспыхивает реже, чем его поймают.

Еще одна болевая точка - это, вероятно, создание элементов. Можете ли вы опубликовать этот код? Часто бывают простые оптимизации, которые приводят к значительному увеличению производительности.

Обновление

Начиная с jQuery 1.7, метод .live () устарел. Используйте .on () для присоединения обработчиков событий. Пользователям старых версий jQuery следует использовать .delegate () вместо .live () - JQuery Docs

2 голосов
/ 19 марта 2010

Свяжите ваше событие click со всем документом, и в функции посмотрите на event.target, чтобы увидеть, на каком элементе продукта был фактически нажат. Таким образом, вам нужно сделать только одно связывание.

0 голосов
/ 19 марта 2010

Во-первых, используйте встроенный в Firebug профилировщик, чтобы проверить, где находится большая часть задержки; просто нажмите «профиль», запустите медленное действие, нажмите его снова и посмотрите, какие звонки самые дорогие.

Во-вторых, посмотрите на «живую» обработку событий: http://api.jquery.com/live/

Способ, которым это работает, заключается в том, что есть только один обработчик событий, который просматривает весь документ и делегирует обработчикам живых событий. Это работает намного быстрее, когда у вас есть множество элементов, потому что вам не нужно добавлять обработчик событий для каждого элемента отдельно.

0 голосов
/ 19 марта 2010

вы должны взглянуть на jqrid или flexigrid что-то, что позволит вам делать пейджинг, который позволяет выводить данные сразу, поэтому лучше ограничить объем, который вы выводите за раз даже если эти вещи подходят для вашего проекта, вы должны выяснить, как ограничить данные, это нижняя строка

...