Pull to refresh

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

Reading time 4 min
Views 2.2K
В свое время я прибывал в уверенности, что код
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:
Hubs:
+17
Comments 21
Comments Comments 21

Articles