Эффективность связывания jQuery

У меня проблема со скоростью загрузки при использовании нескольких привязок 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
    );
});

person clownshoes    schedule 19.03.2010    source источник


Ответы (4)


Вы привязываете обработчик 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

person Nick Craver    schedule 19.03.2010
comment
Live - победитель! Теперь мое единственное зависание на скорости - это скачанный мной подключаемый модуль без щелчка правой кнопкой мыши. Без привязок создание списка происходило мгновенно, теперь это примерно полсекунды. Со сценарием без щелчка правой кнопкой мыши он зависает, но это связано с привязками, которые я себе представляю. Большое спасибо! - person clownshoes; 19.03.2010
comment
@chelfers - Какой плагин без щелчка правой кнопкой мыши вы используете? Также должно быть довольно легко переключиться на .live() и мгновенно получить весь ваш код ... если вы еще этого не сделали, ответьте здесь, и я посмотрю. - person Nick Craver; 24.05.2010
comment
delegate() определенно лучший способ. Это намного оптимальнее, чем альтернативы, когда у вас есть тысячи элементов, события которых вы хотите фиксировать. Единственное предостережение: для этого требуется jQuery 1.4. - person Asbjørn Ulsberg; 24.08.2010
comment
святое дерьмо! это было удивительно! У меня возникла та же проблема, и небольшое изменение кода с .change (function на .live ('change', function просто решило все! Мне нравится jQuery, и мне нравится ваш ответ, Ник! Спасибо !! - person Matt; 03.08.2011

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

person Jacob Mattison    schedule 19.03.2010
comment
Возможно, лучше не привязывать его ко всему документу, а к родительскому элементу ul или ol. Я определенно не стал бы использовать live, так как это также имеет проблемы с производительностью, которых в данном случае можно полностью избежать. - person Jan; 13.02.2012

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

person mcgrailm    schedule 19.03.2010
comment
Проблема в том, что мне нужны все данные на одной странице по запросу клиента. Я уже построил систему подкачки, но не использовался -_- - person clownshoes; 19.03.2010

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

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

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

person Alexander Malfait    schedule 19.03.2010
comment
Ездил с живой обработкой. Профайлер не слишком помог, поскольку дал мне общее представление о том, что, как я уже знал, тормозит сценарий. - person clownshoes; 19.03.2010