Pull to refresh

Ревизия кода Ext JS/ GridView

Designing and refactoring
В свое время я прибывал в уверенности, что код
js обычно не нужно писать так, чтобы он был
наиболее оптимальным. «Клиентская часть» — говорил я, — «на сервер никак не
повлияет, а посему, можно забить». К сожалению, оказалось, что это не совсем
так.

Данная статья содержит технические сведения. Если вы не понимаете о чем здесь написано, пожалуйста, не минусуйте.


Началось все с использования библиотеки
EXT JS на нашем проекте, а
конкретно – виджета EditableGrid. Первоначально
библиотека очень понравилась. Прежде всего своей объектно-ориентированной
структурой. Проблемы начались позже. Забегая вперед скажу, что я все еще
остаюсь поклонником EXTJS. Другой библиотеки, которая была бы такой же
логичной и предлагала такие возможности я не знаю. Кроме того, следует
отметить, что очевидные проблемы с производительностью начинались либо при
большом количестве колонок в таблице, либо при большом количестве строк (про
это разработчики библиотеки, впрочем, предупреждали).

Про некоторые общие проблемы js вы можете прочесть здесь




CSSCascadingStyleSheets – “а для чего слово
каскадные?”




На самом деле, на эту проблему мне указал наш
html кодер (Женя, привет!
J)

Взгляните на css файл,
который используется.

Да, иногда стили специфицируются каскадно, но в
подавляющем большинстве – НЕТ. «В чем же проблема» — спросите Вы. Для меня,
как для программиста на java, проблемы не
существовало до тех пор, пока я не внедрил грид на отверстанную страницу. И…
у меня поплыли все стили. Грид выглядел ужасно. В чем дело? Дело в том, что на
странице использовался общие css стили для всего
проекта и они имели приоритет выше, чем те стили что описаны в
grid.css. Почему
так – я Вам не объясню. Я понимаю это как «чем точнее задан путь, тем выше
приоритет у стиля», по крайней мере такой объяснение для меня работает. Есть
еще модификатор «!important», но как мне рассказали, этим лучше не
злоупотреблять. Надеюсь, учитывая количество профессиональных дизайнеров
здесь, в комментариях будет объяснение.

Итак, для себя я сделал вывод – использовать слово
«каскадные» в определении CSS.



Обновление CSSправил или первые тормоза



Вышло так, что по требованиям в одном из гридов нужно
было отображать 20 колонок. «Небольшая цифра» — как я думал. Оказалось, что
нет.

Ext.grid.GridViewиспользует забавный механизм для указания ширины колонок. При отрисовке
создается узел <style> в который
записываются пустые стили вида:



#[идентификатор грида]
.x-grid-col-[номер
колонки] {

2}



Например:



#grid-example .x-grid-col-0 {

2}





Когда html код готов,
происходит изменение этих динамически сгенерированных стилей и указывается
ширина каждой колонки. Для каждого такого стиля выполняется



Ext.util.CSS.updateRule



Надо сказать, что это не дешевая операция. А для 20ти
колонок наблюдались заметные тормоза. Таким образом пришлось оптимизировать
этот механизм, чтобы убрать ощутимую паузу, которая происходила с момента
загрузки, до того момента, когда пользователь мог реально что-то сделать.
Кроме того, загрузка процессора была 100%.

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

Итак, для себя я сделал вывод – не использовать
динамическое обновление таблиц CSS.



Большое количество элементов или «ну сколько можно
пихать?»




Примерно такой код Вы увидите для каждой ячейке в
гриде:



<td class=«x-grid-col x-grid-td-1
x-grid-cell-5-1» tabindex=«0»>

<div class=«x-grid-col-1
x-grid-cell-inner»>

<div class=«x-grid-cell-text» unselectable=«on»>$31.61</div>

</div>

</td>



Это только ОДНА ячейка. Получается, что кроме
td, несчастному броузеру нужно будет держать еще
как минимум два DOM объекта. Это занимает память
и ресурсы.

На мой взгляд, этого нужно избегать.



Работа с DOMтаблицей или «ну вот оно и умерло»

Надо отметить, что на форумах разработчики честно
предупреждают о том, что работа с большим количеством строк будет тормозить и
следует использовать разбивку на страницы. Но… пользователи всегда правы и
страницы видеть не захотели. На самом деле, существует простой способ
оптимизировать грид для работы с довольно большим количеством строк (у меня
работает с 500 без тормозов).



Какая была проблема? Дело в том, что
GridView для представления использует таблицу.
Операции по удалению/вставке/редактированию работали очень медленно, если
количество строк было больше 20 (при количестве колонок больше 15ти). Оно и
понятно, таблица – это не просто массив, а целый объект, которые нужно
пересчитать/перерисовать. Кроме того, при изменении всех значений в какой-либо
колонке (например, вычисляемая колонка, которая зависит от внешнего параметра)
броузер просто умирал и в себя уже не приходил.



Как это решилось? Из профайла я понял, что работа с
большими таблицами (> 20-30 строк) занимает на порядок больше времени, чем
с маленькими (< 20 строк). После этого я глянул на реализацию
Google Spreadsheet. Вот
что я там обнаружил: они не используют одну большую таблицу, а разбивают на
много маленьких, которые располагаются одна под одной. Кроме того, ширина
колонок задается не стилями, а, что более логично, через ширину первой строки
с использованием стиля
table-layout:
fixed.



Результат

Таким образом, GridViewбыл переписан с учетом следующих правил:

— Использовать КАСКАДНЫЕ стили

— Не добавлять лишних элементов в
DOM

— Не использовать динамическое обновление стилей

— Разбивать большие таблицы на несколько
маленьких

В результате я получил
EditableGrid, который может работать с большим
количеством строк.

Tags:extjsjsоптимизация jsвиджет
Hubs: Designing and refactoring
Total votes 27: ↑22 and ↓5 +17
Views1.9K

Comments 21

Only those users with full accounts are able to leave comments. Log in, please.

Popular right now

JS разработчик
from 130,000 to 180,000 ₽HR PrimeМосква
Младший разработчик JavaScript (ExtJS)
from 45,000 to 64,000 ₽Exactpro SystemsСаратов
Full Stack JS Developer
from 3,000 to 4,500 $923 DigitalRemote job
Middle Frontend Developer (JS)
from 100,000 to 150,000 ₽Krew GuruRemote job
Middle JS разработчик (React+TypeScript)
from 90,000 to 130,000 ₽HolyWebRemote job

Top of the last 24 hours