- PVSM.RU - https://www.pvsm.ru -

Оптимизация обработки сложных селекторов

Оптимизация обработки сложных селекторовCSS селекторы в фронтенде можно сравнить с SQL операторами в бэкенде. Не смотря на их изначальную роль в CSS, мы активно используем селекторы в нашем Javascript коде, и, учитывая декларативный стиль селекторов, они являются приоритетными кандидатами на оптимизацию.

В браузерах существует много вариантов парсинга, обработки и сопоставления большого количества CSS селекторов. Современные веб-приложения используют тысячи селекторов в своих стилях. Чтобы рассчитать стиль для одного элемента, приходится учитывать огромное количество CSS правил. И браузеры не просто обходят все селекторы по кругу – это было бы очень медленно.

Многие браузеры используют специальную группировку данных, отбрасывая селекторы, которые очевидным образом не подойдут. В WebKit-е это выполняет RuleSet [1].

SelectorSet

SelectorSet [2] – это Javascript-имплементация подобной группировки. Если у вас есть набор селекторов, известных заранее – вы можете производить выборку элементов по этим селекторам намного эффективнее.

Добавленные в набор селекторы быстро анализируются и индексируются по ключу. Ключ формируется из значительной правой части селектора. Если селектор нацелен на id – этот id становится ключом. Если в правой части класс, используется класс, и т.д. Затем селектор помещается в карту, проиндексированную ключами. Поиск ключей в карте занимает постоянную времени [3].

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

Ускоряем делегированные события

Наверное, самый известный пример делегирования, это функция jQuery $.fn.live (новое $.fn.on). Основное преимущество использования делегированного обработчика события, вместо привязанного напрямую, является то, что все новые элементы, добавленные после события DOMContentLoaded, будут также вызывать этот обработчик. Подобный подход часто просто незаменим. К примеру, в таком паттерне, как pjax [4], когда вся страница никогда не перегружается.

Но чрезмерное делегирование событий на document, таких как $(‘.foo’).live(‘click’), или $(document).on(‘click’, ‘.foo’) — чревато. Основной проблемой является то, что селектору приходится обходить всю цепь предков элемента, вызвавшего событие. В крупных приложениях с большими и сложными DOM, уровень вложенности может быть 15 и выше. Но это не самое печальное. Самое интересное начинается, когда делегированных селекторов становится много. GitHub использует больше 100, а Basecamp – больше 300 событий, делегированных на document.

Но,

если сюда применить вышеописанный подход группировки селекторов, в виде патча к jQuery [5], можно значительно увеличить обработку событий в вашем приложении. Оцените разницу в небольшом тесте [6], в котором используются реальные разметка и селекторы с GitHub.

На самом деле, обе эти библиотеки должны быть заменены средствами самих браузеров. Они, конечно же, уже используют свои подходы для оптимизации CSS, но, как ни печально, у них все еще нет нативной реализации декларативных обработчиков событий, хотя некоторые люди используют это с 2006 года [7].

Ссылки на используемые бибилиотеки

github.com/josh/selector-set [2]
github.com/josh/jquery-selector-set [5]

Автор: creage

Источник [8]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/javascript/53520

Ссылки в тексте:

[1] RuleSet: https://github.com/WebKit/webkit/blob/c0885665302c752230987427d4021b6df634087d/Source/WebCore/css/RuleSet.cpp

[2] SelectorSet: https://github.com/josh/selector-set

[3] постоянную времени: http://mjwilcox.net/archives/137

[4] pjax: https://github.com/defunkt/jquery-pjax

[5] патча к jQuery: https://github.com/josh/jquery-selector-set

[6] небольшом тесте: http://jsperf.com/jquery-selector-set-trigger

[7] 2006 года: http://danwebb.net/2006/9/3/low-pro-unobtrusive-scripting-for-prototype

[8] Источник: http://habrahabr.ru/post/210270/