Оптимизация JavaScript часть 2: Применение стилей к элементам

Это вторая часть цикла статей, посвященных оптимизации JavaScript. В этой заметке я рассмотрю динамическое изменение стилей элементов и немного раскрою процесс рендеринга HTML. Кроме того, в этой заметке вы найдете некоторые трюки, позволяющие сделать Ваши приложения быстрее.

Стили или классы?

Сценарий: Ваш документ содержит элементы, у которых нужно поменять цвет, фон или что-нибудь еще, относящееся к стилям. Например, подсветить строки таблицы при наведении мыши или пометить их, если выбран соответствующий чекбокс.

И снова, я знаю два способа: используя стили или установив цвет (или фон) напрямую из JavaScript. Для начала немного тестов:

var items = el.getElementsByTagName('li');

for (var i = 0; i < 1000; i++) {
    items[i].className = 'selected'
}

Средний результат 187 – 291 мс, для Internet Explorer 6 время составило 512 мс, и в Opera 9 оно равно 47 мс.

var items = el.getElementsByTagName('li');

for (var i = 0; i < 1000; i++) {
    items[i].style.backgroundColor = '#007f00';
    items[i].style.color = '#ff0000';
}

Результаты тестов

Я получил результаты, начинающиеся с 282 мс в Opera 9 и заканчивающиеся 1709 мс в Internet Explorer 6.

Результаты простые и понятные:

МетодIE 6IE 7FF 1.5FF 2.0Opera 9
1element.className51218729120347
2element.style.color1709422725547282

Тест производительности: Применение стилей к элементам

Тест производительности: Применение стилей к элементам

Плавное изменение

Вы можете посмотреть тест и получить собственные результаты производительности здесь.

Похоже на то, что это самая малозначимая статья цикла, но есть одна штука с Internet Explorer — обновление страницы. Помните сценарий, описанный в начале статьи, об onmouseover? Когда Вы изменяете имя класса элемента, Ваш код значительно быстрее отрабатывает, но вот страница обновляется медленно. Взгляните на пример. Попробуйте кликнуть Generate elements, когда выбрана опция element.className. Попробуйте подвигать мышкой над элементами, проскроллить список до конца и подвигать снова (для медленных машин количество элементов будет меньше установленного по умолчанию, для более быстрых — больше). Вы заметили, что фон сильно отстает от курсора мыши? Теперь переключите на element.style.color (не забудьте снова нажать Generate elements). Фон изменяется более плавно, правда?

Перерисовка страницы

Внизу страницы вы видите количество пойманных событий onmouseover и среднее время, потраченное на их обработку. Как Вы могли заметить, в первом случае код отрабатывает более чем в два раза быстрее! Почему же выглядит медленнее? Я думаю, все из-за того, что изменение свойства className в Internet Explorer не перерисовывает страницу мгновенно, вместо этого он просто помещает событие обновления в очередь. Отсюда и огромная скорость, казалось бы, более сложной процедуры. Если у Вас есть другие идеи, пожалуйста, отпишитесь в комментариях.

Те, кто дочитал до этого места, наверняка скажут: »Ээээ, товарищ, ты хитришь. А где же :hover?«. Спешу исправить положение и дописываю этот вариант. Во-первых, эта штука не работает в Internet Explorer 6 (и не надо спрашивать «кому он нужен?»). Но это не самая большая проблема, намного хуже дела обстоят с производительностью. Даже комментировать не хочу, просто выберите третий радиобаттон на приведенной выше странице и подвигайте мышью в Internet Explorer 7 и Opera 9.

Выводы

  • Используйте className везде, где это возможно. Это дает Вам больше гибкости и контроля над внешним видом сайта.
  • Если у Вас много элементов в контейнере, и необходимо построить очень быстрый интерфейс, устанавливайте стили напрямую через свойство style элементов.

Читать дальше

Все комментарии