JavaScript: преимущества и недостатки динамического (на лету) создания элемента стиля
В JavaScript мы можем создать элемент <style>
динамически и добавить в раздел <head>
, чтобы применить правило CSS для огромного количества элементов.
-
В чем преимущества или недостатки этого подхода?
-
Если это действительно дает прирост производительности по сравнению с итерацией javascript по элементам. Что происходит за сценой (внутри браузера)?
-
Какой из них быстрее или медленнее? Итерация Javascript по элементам или динамическое добавление css в браузере?
-
Как насчет времени обработки? обрабатывающая нагрузка?
Чтобы лучше понять проблему, в которой я использовал этот подход, см. следующий пример:
Пример: Если у меня есть таблица с 20 или более столбцами и 1000 строк или более, как указано ниже:
<table border="1" class='no-filter'>
<thead>
<tr>
<th data-title='id'>Id</th>
<th data-title='name'>Name</th>
<th data-title='family_name'>Family Name</th>
<th data-title='ssn'>SSN</th>
//Other table data
</tr>
</thead>
<tbody>
<tr data-id='1' data-name='nick' data-famil_name='jackson' data-ssn='123456'>
<td class="column column1">1</td>
<td class="column column2">Nick</td>
<td class="column column3">Jackson</td>
<td class="column column4">123456</td>
//Other table data
</tr>
//Other rows
<tr data-id='809' data-name='helga' data-famil_name='jhonson' data-ssn='125648'>
<td class="column column1">809</td>
<td class="column column2">Helga</td>
<td class="column column3">Jhonson</td>
<td class="column column4">125648</td>
//Other table data
</tr>
//Other rows
<tr data-id='1001' data-name='nick' data-famil_name='jhonson' data-ssn='216458'>
<td class="column column1">1001</td>
<td class="column column2">Nick</td>
<td class="column column3">Jhonson</td>
<td class="column column4">216458</td>
//Other table data
</tr>
//Other rows
</tbody>
</table>
Если кому-то нужен пример jsFiddle, я могу его создать позже.
Случай 1: Если я хочу динамически скрыть только столбец таблицы, который содержит данные SSN. Я могу применить несколько способов сделать это. Этот подход можно разделить на две основные категории. В решениях первой категории я могу перебирать элементы td
и динамически изменять стиль для столбца. В втором подходе я могу применять CSS, динамически создавая одноразовые правила предопределенного CSS, как указано здесь @Frits van Campen. ( Примечание: @Frits van Campen является хорошим решением для данного случая. Но я хочу обсудить дальше, а затем манипулировать показами таблицы и скрывать ее. )
Я могу создать динамическое правило CSS следующим образом:
td:nth-child(3)
{
display:none;
}
Или примените предопределенное правило CSS:
table.no-filter td.column3
{
display:block;
}
table.filter3 td.column3
{
display: none;
}
Вот примеры jsFiddly:
Вот сравнение времени с помощью метода console.time, который я нашел здесь.
![enter image description here]()
Слева - динамический css, а правый - итерационный.
Возможно, это не подходит, потому что он вычисляет элемент стиля добавления и выполняет итерацию по элементам. Вся итерация по элементу в динамическом CSS будет выполняться внутренними браузерами. Однако, если мы думаем, что наш script ответный динамический css-запрос быстрее. Примечание: итерационный подход будет быстрее в чистом JavaScript по сравнению с jQuery. Но насколько быстрее у меня нет результатов. Таким образом, вы можете больше в своих ответах.
Случай 2: Теперь я хочу выделить строку таблицы <tr>
, которая содержит пользователя с именем "Nick". Здесь вы можете заметить, что в строке таблицы есть атрибуты данных, такие как name, family_name, id и т.д. Итак, здесь я снова могу перебирать элементы с помощью javascript или любых других инструментов библиотеки или применять какое-либо динамическое правило (я не знаю, возможно ли это или не применять предопределенные фильтры, как в случае 1.)
Правило CSS:
tr[data-name ~='nick']
{
background-color:red;
}
В этом случае я могу сделать большую забавную фильтрацию, применяя правило CSS динамически.
Обновление: здесь приведен пример для простого обзора проблемы. И некоторые оптимизированные итерации могут работать одинаково быстро в javascript. Тем не менее, я рассматриваю только таблицу, в которой нет дочерних элементов-ковша, относительно вложенных элементов ul, где перемещение для выбора элемента может быть затруднено.
Важно:. Я приводил только пример таблицы, чтобы пояснить, с какими проблемами я столкнулся, если это не имеет значения, не стесняйтесь редактировать вопрос и удалять эту часть. Кроме того, пожалуйста, четко сформулируйте свои ответы в рамках вопроса. Здесь я не спрашиваю: "Я реализовал это в хорошем смысле или нет?" Я задаю вопрос о преимуществах или недостатках динамического создания элементов стиля с точки зрения внутренних механизмов браузера.
P.S. и пример: Почему я пришел с этой идеей? Я недавно отвечаю за "Как скрыть столбцы в очень длинной таблице html. В этом вопросе OP спрашивает о применении правила CSS для определенных столбцов таблицы в длинной таблице. Я предлагаю создать элемент стиля с правилами на лету, и он отлично работает. Я думаю, это связано с тем, что стиль применяется внутренними механизмами браузеров и обеспечивает лучшую производительность, чем повторение элементов и применение стиля к каждому элементу.
Ответы
Ответ 1
Помимо некоторых проблем, связанных с определением области охвата (на странице может быть больше таблиц...), в этом подходе нет ничего неправильного - элементы style
находятся в DOM для редактирования по своему усмотрению, браузеры соблюдают эти стандарты. В вашем тестовом случае действительно нет действительного другого подхода, так как действительно colgroup
имеет чрезвычайно грязную поддержку - в Bugzilla имеется 78 дубликатов ошибок, и Mozilla отказывается реализовывать их правильно, поскольку первый связанный отчет об ошибках в 1998 году.
Причина, по которой это быстрее, - это просто одна из накладных расходов - после того, как полная DOM будет собрана, относительно небольшая таблица стилей может быть применена в родном С++ намного быстрее, чем интерпретатор Javascript может перебирать все строки и ячейки. Это связано с тем, что исторически правила CSS применяются в обратном порядке, и браузер сохраняет словарь внутри, что позволяет ему находить все элементы td
. Native С++ всегда будет бить более сложный код на основе интерпретатора.
В будущем проблема с областью охвата также может быть решена с помощью областей с привязкой (в настоящее время только в FF, довольно типично), вы бы кодирование следующим образом:
<table>
<style id="myTableStyle" scoped>
td:nth-child(1) { display:none }
</style>
<tbody>
...
</tbody>
</table>
Атрибут scoped
делает скрытые стили действительными только для его содержащего элемента, table
в этом случае и, конечно, все его содержащиеся элементы. И поскольку вы можете получить к нему доступ по идентификатору, содержимое легко заменяется/реконструируется.
В то время как это было бы предпочтительнее вашего подхода, пока нет универсальной поддержки браузера для этого создания элементов style
в head
, это лучший способ обхода.
Ответ 2
Динамическое создание CSS плохое. Не делайте этого.
Решение, которое работает при генерации динамического CSS, может быть преобразовано в решение, которое не требует динамического CSS.
Если вам нужен пример, см. мой ответ здесь: jQuery для обновления фактического CSS
Чтобы напрямую ответить на связанный с вами случай:
Это кажется мне очень странным случаем. Страница с таблицей с 1000 строк уже является плохой стартовой позицией. Вы не можете разумно подогнать 1000 строк на экране и ожидать какого-либо полезного взаимодействия. CSS здесь не проблема. Если таблица была меньше, проблема с производительностью исчезает.
Существуют, возможно, другие подходы, чем на OP. Вам не нужно (динамически) добавлять класс в каждую ячейку, вы можете поместить класс туда во время генерации, например:
<table class="no-filter">
...
<td class="filter1 filter2"></td>
...
</table>
Затем сделайте что-то вроде:
table.filter1 td.filter2 { display: none; }
table.filter2 td.filter1 { display: none; }
Вы только меняете класс в таблице, чтобы сказать, какой фильтр применяется.
CSS - это не просто молот, а целый набор очень утонченных и очень мощных инструментов. Убедитесь, что вы используете правильные.
Преимущества использования статического CSS должны быть очевидными:
- Намного легче понять, протестировать, отладить и поддерживать.
- CSS фактически находится в CSS (не в JavaScript).
- Вы можете делать шаблоны, возможно, добавить некоторые визуальные регрессионные тесты.
Есть также некоторые проблемы с производительностью. Я вижу поставщиков браузеров, оптимизирующих AGAINST dynamic CSS. Под этим я имею в виду, если есть оптимизация для статического CSS, которая снижает производительность динамического CSS, вы просто можете сделать этот компромисс.
Ответ 3
Имеется библиотека под названием less.js, которая позволяет вам манипулировать css с переменными в файле your.css. Это очень хорошая библиотека, и вы можете взглянуть на нее.
http://www.lesscss.org/