Современный пользователь ожидает, что корпоративное приложение будет работать одинаково хорошо везде: на широком мониторе трейдера в офисе, на планшете менеджера на встрече, на смартфоне сотрудника в командировке. Задача адаптации интерфейса под все эти сценарии может показаться сложной, но Ext JS предоставляет для её решения полноценный набор инструментов — от гибкой системы макетов до декларативного управления конфигурацией компонентов.
В этой статье мы разберем, как устроен блок Adaptive в Ext JS: какие инструменты он включает, как они работают вместе и почему адаптивность в Ext JS — это не «дополнительная фича», а архитектурная основа для создания корпоративных приложений.
🧩 Проблема: почему адаптивность — это сложно
В обычной веб-разработке адаптивность часто сводится к написанию CSS-медиазапросов. Вы определяете несколько контрольных точек (breakpoints) и для каждой пишете отдельный набор стилей. Этот подход работает для простых сайтов, но плохо масштабируется для сложных корпоративных интерфейсов.
Почему:
-
Компоненты, а не HTML: Ext JS-приложение состоит из десятков компонентов (Grid, Tree, Form, Panel), каждый из которых имеет собственную структуру и поведение. Написать CSS для каждого из них на каждом разрешении — это огромный объём ручной работы.
-
Динамические изменения: Пользователь может изменить размер окна браузера, повернуть планшет, подключить внешний монитор. Интерфейс должен реагировать на эти изменения в реальном времени, а не только при загрузке страницы.
-
Сохранение контекста: При изменении размера экрана важно не просто «переставить» компоненты, а сохранить логику работы: данные, выбранные элементы, состояние фильтров.
Ext JS решает эти проблемы на уровне архитектуры компонентов, а не через CSS.
🏗️ Инструмент 1: Layout Manager — гибкая система макетов
Layout Manager — это основа адаптивности в Ext JS. Каждый контейнер в приложении имеет макет (layout), который определяет, как располагаются и изменяются размеры его дочерних компонентов.
Ключевые макеты:
-
Fit — единственный дочерний компонент растягивается на всю доступную область контейнера. Идеально для случаев, когда нужно, чтобы один компонент (например, Grid) занимал всё пространство.
-
HBox — дочерние компоненты располагаются горизонтально. Каждый может иметь свойство
flex, определяющее, сколько пространства он занимает относительно других. -
VBox — то же самое, но по вертикали.
-
Border — классический макет для корпоративных приложений: центральная область (center) и панели вокруг неё (north, south, east, west).
-
Card — дочерние компоненты накладываются друг на друга, как карточки. Виден только один — используется для мастеров, вкладок, переходов между экранами.
Что это даёт:
Вместо того чтобы вручную рассчитывать пиксели и писать CSS, вы декларативно описываете, как должны располагаться компоненты. Layout Manager автоматически пересчитывает размеры и позиции при изменении размера контейнера.
Пример:
{ xtype: 'container', layout: 'hbox', items: [{ xtype: 'panel', title: 'Навигация', flex: 1, html: 'Боковая панель' }, { xtype: 'panel', title: 'Контент', flex: 3, html: 'Основная область' }] }
Здесь боковая панель занимает 1/4 ширины, а контент — 3/4. При изменении размера окна пропорции сохраняются автоматически.
🎛️ Инструмент 2: responsiveConfig — декларативное управление конфигурацией
responsiveConfig — это, пожалуй, самый мощный инструмент адаптивности в Ext JS. Он позволяет декларативно управлять конфигурацией компонентов в зависимости от текущих характеристик устройства: ширины и высоты viewport, ориентации экрана (портретная/ландшафтная) и даже платформы.
Как это работает:
Вы добавляете в компонент свойство responsiveConfig, которое представляет собой объект, где ключи — это условия (правила), а значения — это конфигурации, которые применяются, когда условие истинно.
Ext.create({ xtype: 'panel', title: 'Some Title', layout: { type: 'hbox' }, responsiveConfig: { 'width < 800': { layout: { vertical: true } }, 'width >= 800': { layout: { vertical: false } } } });
В этом примере: если ширина экрана меньше 800 пикселей, макет становится вертикальным (компоненты располагаются друг под другом), а если больше — горизонтальным.
Доступные переменные в правилах:
В выражениях responsiveConfig можно использовать следующие переменные:
-
landscape—true, если устройство в ландшафтной ориентации (всегдаtrueна десктопе). -
portrait—true, если устройство в портретной ориентации (всегдаfalseна десктопе). -
tall—true, еслиwidth < height(высота больше ширины). -
wide—true, еслиwidth > height(ширина больше высоты). -
width— ширина viewport в пикселях. -
height— высота viewport в пикселях. -
platform— объект с информацией о платформе (например,platform.desktop,platform.tablet).
Пример с комбинацией условий:
responsiveConfig: { 'desktop || width > 800': { region: 'west' }, '!(desktop || width > 800)': { region: 'north' } }
Здесь: если устройство — десктоп или ширина больше 800 пикселей, панель располагается слева (west). В противном случае — сверху (north).
Важное замечание:
Правила в responsiveConfig должны быть взаимоисключающими. Если несколько правил одновременно устанавливают одну и ту же конфигурацию, порядок их применения не определён, и результат может быть непредсказуемым.
🔌 Инструмент 3: Плагин responsive
Для того чтобы компонент начал реагировать на изменения размера экрана, ему нужно включить адаптивность. В Ext JS это делается через специальный плагин.
Как подключить:
Вы можете добавить плагин responsive либо в определение класса (тогда все экземпляры компонента будут адаптивными), либо в конфигурацию конкретного экземпляра.
Ext.define('MyApp.view.Main', { extend: 'Ext.tab.Panel', plugins: 'responsive', responsiveConfig: { landscape: { tabPosition: 'left' }, portrait: { tabPosition: 'top' } }, items: [{ title: 'Foo' }, { title: 'Bar' }] });
В этом примере вкладки (Tab Bar) располагаются слева в ландшафтной ориентации и сверху — в портретной.
Почему плагин, а не встроенная функция?
По соображениям производительности Ext JS-компоненты не являются адаптивными по умолчанию. Включение responsiveConfig для каждого компонента добавляет накладные расходы на отслеживание изменений. Поэтому разработчик сам решает, какие компоненты должны реагировать на изменение размера экрана, а какие — нет.
🧩 Инструмент 4: 12-колоночная сетка (паттерн)
Хотя Ext JS не предоставляет 12-колоночную сетку «из коробки» (как Bootstrap), её легко реализовать с помощью пользовательского макета. Этот паттерн хорошо знаком разработчикам, привыкшим к Bootstrap, и делает код интуитивно понятным.
Пример реализации:
Вы создаёте собственный макет next-grid, который добавляет в элементы контейнера свойство colspan. Это свойство может быть либо числом (фиксированное количество колонок), либо объектом, где для каждого размера экрана указано своё количество колонок.
{ xtype: 'container', layout: { type: 'next-grid' }, defaults: { xtype: 'textfield', labelAlign: 'top' }, items: [{ label: 'First name', placeholder: 'e.g. Mario', colspan: { lg: 6, md: 12, sm: 12 } }, { label: 'Last name', placeholder: 'e.g. Rossi', colspan: { lg: 3, md: 6, sm: 12 } }, { label: 'City', placeholder: 'e.g. Milano', colspan: { lg: 3, md: 6, sm: 12 } }] }
Как это работает:
-
На больших экранах (lg) поле «First name» занимает 6 колонок (половину ширины), а «Last name» и «City» — по 3 колонки каждый. Таким образом, все три поля помещаются в одну строку.
-
На средних экранах (md) «First name» занимает все 12 колонок, а «Last name» и «City» — по 6 колонок каждый. Получается две строки.
-
На маленьких экранах (sm) каждое поле занимает все 12 колонок — по одному полю в строке.
Преимущество:
Такой подход позволяет описывать адаптивность декларативно, без написания отдельных CSS-правил для каждого breakpoint. Вы просто указываете, сколько колонок должен занимать компонент на каждом размере экрана.
🆕 Что нового в Ext JS 8.0
В версии 8.0 блок Adaptive получил несколько важных улучшений:
-
Enhanced Grid Performance и Horizontal Buffering (Modern Toolkit): Grid теперь рендерит только видимые колонки плюс настраиваемый буфер, что позволяет плавно отображать таблицы с более чем 1000 колонок. Это критически важно для адаптивности на широких экранах.
-
Lockable Grid Plugin (Modern Toolkit): Новый плагин позволяет закреплять важные колонки при горизонтальной прокрутке. Это особенно полезно на устройствах с узкими экранами, где нужно сохранять контекст (например, имя или ID) при просмотре широких таблиц.
-
Responsive Digital Signature Pad: Новый компонент для сбора подписей, который адаптируется как к мыши на десктопе, так и к сенсорному вводу на планшетах. Поддерживает Undo/Redo, настройку пера и экспорт в PNG, JPEG и SVG.
💎 Заключение
Блок Adaptive в Ext JS — это не просто «адаптивная вёрстка». Это архитектурный подход к созданию интерфейсов, которые одинаково хорошо работают на любых устройствах и в любых условиях.
| Инструмент | Что решает |
|---|---|
| Layout Manager | Гибкое управление расположением и размерами компонентов |
responsiveConfig |
Декларативное управление конфигурацией в зависимости от размера и ориентации экрана |
Плагин responsive |
Включение адаптивности для конкретных компонентов |
| 12-колоночная сетка | Паттерн для описания адаптивных форм и дашбордов |
| Улучшения Grid в 8.0 | Производительность при работе с широкими и большими наборами данных |
В большинстве фреймворков вам пришлось бы собирать адаптивность из медиазапросов, JavaScript-обработчиков и сторонних библиотек. В Ext JS всё это встроено, интегрировано и работает согласованно.
Если вы строите корпоративное приложение, которое должно работать на десктопах, планшетах и смартфонах, — блок Adaptive в Ext JS заслуживает самого пристального внимания.
Если у вас есть опыт создания адаптивных приложений на Ext JS или вопросы по layout-менеджерам и responsiveConfig, поделитесь в комментариях.