Adaptive в Ext JS: как создавать интерфейсы, которые работают на любом устройстве

Современный пользователь ожидает, что корпоративное приложение будет работать одинаково хорошо везде: на широком мониторе трейдера в офисе, на планшете менеджера на встрече, на смартфоне сотрудника в командировке. Задача адаптации интерфейса под все эти сценарии может показаться сложной, но 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 автоматически пересчитывает размеры и позиции при изменении размера контейнера.

Пример:

javascript
{
    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, которое представляет собой объект, где ключи — это условия (правила), а значения — это конфигурации, которые применяются, когда условие истинно.

javascript
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).

Пример с комбинацией условий:

javascript
responsiveConfig: {
    'desktop || width > 800': {
        region: 'west'
    },
    '!(desktop || width > 800)': {
        region: 'north'
    }
}

Здесь: если устройство — десктоп или ширина больше 800 пикселей, панель располагается слева (west). В противном случае — сверху (north).

Важное замечание:
Правила в responsiveConfig должны быть взаимоисключающими. Если несколько правил одновременно устанавливают одну и ту же конфигурацию, порядок их применения не определён, и результат может быть непредсказуемым.

🔌 Инструмент 3: Плагин responsive

Для того чтобы компонент начал реагировать на изменения размера экрана, ему нужно включить адаптивность. В Ext JS это делается через специальный плагин.

Как подключить:

Вы можете добавить плагин responsive либо в определение класса (тогда все экземпляры компонента будут адаптивными), либо в конфигурацию конкретного экземпляра.

javascript
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. Это свойство может быть либо числом (фиксированное количество колонок), либо объектом, где для каждого размера экрана указано своё количество колонок.

javascript
{
    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, поделитесь в комментариях.

Оставьте комментарий