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/