2010-07-15 5 views
2

У меня есть страница, которая выбирает все элементы в форме и сериализующую их так:Фильтрующие элементы из селектора JQuery

var filter = 'form :not([name^=ww],[id$=IDF] *,.tools *)'; 
var serialized = $(filter).serialize(); 

Это работает, если форма не получает около 600+ элементов. Затем пользователь получает ошибку javascript, говорящую о том, что скрипт работает медленно и может сделать их браузеры невосприимчивыми. Затем он дает им возможность прекратить выполнение сценария.

Я попытался использовать фильтры отдельно, я попытался использовать .not на селекторах, а затем сериализовал их, но я столкнулся с одной из двух проблем. Либо он работает быстрее без ошибки, но также не фильтрует элементы, или он фильтрует элементы и дает мне медленную ошибку сценария.

Любые идеи?

+2

* почему, о, почему * у вас было бы 600 элементов ввода в форме в html!?!? –

+0

Ваша проблема не в селекторе. переделайте свою страницу так, чтобы она использовала меньше полей ввода. переработайте свою логику так, чтобы она не требовала сериализации сотен элементов в скрипте. –

+0

с меньшим количеством полей ввода не является вариантом. Я не могу вдаваться в подробности, но это по дизайну –

ответ

5

С 600+ элементов это собирается быть мертвым медленно. Вы должны предложить Sizzle (механизм выбора jQuery) некоторые возможности для оптимизации.

Во-первых, учитывать тот факт, что JQuery можно использовать изначально поддерживаемый querySelectorAll метод (в современных браузерах), если ваш селектор соответствует требованиям CSS3 spec (или, по крайней мере, в той степени, что в настоящее время поддерживается в браузерах).

В вашем случае это означает, что только один простой селектор до :not вместо 3 (1 простой, 2 комплекс).

form :not([name^=ww]) 

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

Посмотрите на свой селектор и подумайте о том, насколько сильно Sizzle имеет отношение к каждому элементу. Сначала ему нужно получить ВСЕ элементы на странице (вы не pre-qualifying:not селектор с тегом/классом/id). Затем на каждом элементе он делает следующее:

(предположим, что он выходит, если результат проверки является ложным)

  1. Убедитесь, что родитель имеет предка с nodeName.toLowerCase() из form.
  2. Проверьте, что у него нет атрибута name, начиная с ww (базовая операция indexOf).
  3. Убедитесь, что у него нет предка с атрибутом id, оканчивающимся на IDF. (дорогостоящая операция)
  4. Убедитесь, что у него нет предка с атрибутом class, содержащим tools.

Последние две операции выполняются медленно.

Это может быть лучше, чтобы вручную построить filter функцию, например, так:

var jq = $([1]); 
$('form :input').filter(function(){ 

    // Re-order conditions so that 
    // most likely to fail is at the top! 

    jq[0] = this; // faster than constructing a new jQ obj 

    return (

     !jq.closest('[id$=IDF]')[0] 
      // this can be improved. Maybe pre-qualify 
      // attribute selector with a tag name 

     && !jq.closest('.tools')[0] 

     && this.name.indexOf('ww') !== 0 

    ); 

}); 

Примечание: эта функция не тестировалась. Надеюсь, вы получите идею ...

+1

+1 Хороший анализ. –

+0

Ничего себе, отлично выглядит! Я дам ему попробовать и опубликовать результаты здесь. Благодарю. –

+0

Я могу добавить, что я мог бы помочь в оптимизации этого больше, если бы увидел разметку. У меня все еще есть вопросы относительно этого ... например: сколько элементов '[id $ = IDF]' есть, и являются ли они разными тегами? Разве нет способа получить тот же класс? – James

1

Не могли бы вы просто сериализовать всю форму и сделать свою фильтрацию на бэкэнде? Кроме того, почему-ой-почему форма растет до 600+ полей?

+0

Это сработает, но мне нужно сделать некоторую логику в сериализованной форме, прежде чем делать postback –

+0

Ну, я бы попытался отправить обратно все данные, необходимые для выполнения эта логика возвращается с запросом и снова позволяет бэкэнду делать это. Таким образом, вы просто «сериализуете» на всей форме, которая должна быть довольно быстрой (например, не в списке, а в одном элементе формы), а затем просто покажите spinner, пока бэкэнд взломает. – rfunduk

0

использовать селектор :input, чтобы выбрать только применимые элементы ..

+0

Я дам вам попытку –

+0

@barlow, я думаю, что мой ответ может быть неправильным .. Я считаю, что сериализация только выбирает элементы ': input' по умолчанию ... но jQuery api-сайт пока недоступен и не может проверить .. –

Смежные вопросы