JQuery addClass и removeClass эффективность - PullRequest
2 голосов
/ 25 августа 2011

Я создаю сортируемую таблицу и мне нужно обновить значки «порядка сортировки» в заголовке таблицы.

Вот небольшая информация, чтобы вы могли лучше понять, что делает мой код.

Код выполняется из события щелчка, и $(this) ссылается на ячейку заголовка таблицы, по которой щелкают.

В ячейке заголовка таблицы есть три интервала; Обертка, текстовый интервал и значок. Вот как это выглядит

<span class='ui-button ui-widget ui-state-default ui-button-text-icon-secondary'>
  <span class='ui-button-text'>text</span>
  <span class='ui-button-icon-secondary ui-icon ui-icon-triangle-2-n-s'></span>
</span>

collection - возврат от $("thead:first th")

и вот мой код, который переключает значки.

var new_class = sort_info.order == "asc" ? "ui-icon-triangle-1-n" : "ui-icon-triangle-1-s";
collection.find(".ui-icon").removeClass("ui-icon-triangle-1-n ui-icon-triangle-1-s ui-icon-triangle-2-n-s").addClass("ui-icon-triangle-2-n-s");
$(this).find(".ui-icon").removeClass("ui-icon-triangle-1-n ui-icon-triangle-1-s ui-icon-triangle-2-n-s").addClass(new_class);

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

Это лучший способ сделать это? Это работает ... и выполняется примерно за 7 мс (Windows 7, FF6.0), что мне в порядке ... просто похоже, что много работы уже сделано.

есть мысли?

Ответы [ 2 ]

4 голосов
/ 25 августа 2011

Если у вас нет других динамических классов, назначаемых этим объектам, вы можете заменить o.removeClass().addClass() на o.attr("className", xxx), поскольку вы знаете, каким должен быть конечный результат, и можете ускорить его в 3 раза (в моем тестовом случае).

С вашим HTML и вашим кодом, я думаю, это может быть сведено к следующему:

var new_class = sort_info.order == "asc" ? "ui-icon-triangle-1-n" : "ui-icon-triangle-1-s";
collection.find(".ui-icon").attr("className", "ui-button-icon-secondary ui-icon ui-icon-triangle-2-n-s"); 
$(this).find(".ui-icon").attr("className", "ui-button-icon-secondary ui-icon " + new_class);

Это должно быть быстрее, потому что вдвое меньше вызовов jQuery, а просто установка атрибута намного быстрее, чем addClass() и removeClass(), но это также более хрупко и немного менее читабельно для тех изменений, которые вы на самом деле пытаетесь делать. Если вы когда-нибудь решите добавить больше классов к этим объектам, этот код придется изменить, чтобы учесть их. Только вы можете решить, стоит ли эта дополнительная производительность небольшого снижения удобства обслуживания.

Вы можете уменьшить количество операций выбора, выполнив всего одну операцию выбора, а затем выполнить итерацию по ней с помощью пользовательской функции, чтобы определить, относится ли каждый объект к этому или нет, и назначить ему соответствующее имя класса. Это одновременно уменьшает количество запросов DOM, но также предотвращает повторное назначение className. Это будет выглядеть примерно так:

var new_class = sort_info.order == "asc" ? "ui-icon-triangle-1-n" : "ui-icon-triangle-1-s";
var that = this;
collection.find(".ui-icon").each(function() {
    if ($.contains(that, this)) {
        this.className = "ui-button-icon-secondary ui-icon " + new_class;
    } else {
        this.className = "ui-button-icon-secondary ui-icon ui-icon-triangle-2-n-s";
    }
});

Поместив все три из них в jsperf тест с только 10 элементами в итерации, я получаю это в Chrome:

Your method: 6691 ops/sec
Direct set of className: 11,210 ops/sec
Iteration with single selector: 20,280 ops/sec

В Firefox 6 я получаю еще более существенную разницу (ваш метод еще медленнее, мой быстрый еще быстрее).

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

1 голос
/ 25 августа 2011

Я думаю, это не будет иметь большого значения, но, может быть, это быстрее (и вы знаете, как это измерить, поэтому я позволю вам быть судьей):

var new_class = sort_info.order == "asc" ? "ui-icon-triangle-1-n" : "ui-icon-triangle-1-s";
collection.not(this).find(".ui-icon-triangle-1-n, .ui-icon-triangle-1-s").removeClass("ui-icon-triangle-1-n ui-icon-triangle-1-s").addClass("ui-icon-triangle-2-n-s");
$(this).find(".ui-icon").removeClass("ui-icon-triangle-1-n ui-icon-triangle-1-s ui-icon-triangle-2-n-s").addClass(new_class);

Но это победило 'это не так важно.

...