Компоненты, контейнеры и лейауты в Ext JS 6

Компоненты

Все компоненты берут своё происхождение из Ext.Component. Все компоненты имеют свойство xtype. Оно очень полезно, когда вы не хотите создавать компонент немедленно, а хотите "лениво" подгрузить его позже.

Контейнеры

Контейнеры это специальные компоненты, которые могут содержать в себе другие компоненты. Ext.container.Container является базовым классом для контейнеров.

В качестве встроенных компонентов можно привести Ext.toolbar.Toolbar, Ext.panel.Panel, и Ext.Editor. Они могут содержать в себе другие компоненты.

Ext.button.Button не унаследован от  Ext.container.Container поэтому он не может содержать в себе другие компоненты.


Типичное Ext JS приложение содержит в себе множестве вложенных компонентов:
Ext.create('Ext.panel.Panel', {
 renderTo : Ext.getBody(),
 width : 700,
 height : 400,
 items: [
 {
   xtype: 'panel',
   title: 'Panel 1',
 },
 {
   xtype: 'panel',
   title: 'Panel 2',
   height: 200,
   items: [
    {
     xtype: 'button',
     text: 'Click Me'
    }
   ]
 },
 {
   xtype: 'panel',
   title: 'Panel 3',
   width: 150,
   height: 100,
 }
 ]
});
Схематичное представление вышеприведенного кода
Результирующий вид вышеприведенного кода

Лейауты

Лейаут определяет позицию и размеры содержащихся в нем компонентов. Каждый контейнер имеет лейаут. По умолчанию используется auto лейаут. Он не определяет никаких правил для позиционирования и размерности дочерних компонентов. На вышеприведенном рисунке используется auto лейаут.

Рассмотрим пример использования column и center лейаута. При использовании колоночного лейаута можно задавать ширину столбца columnWidth. Сумма всех columnWidth должна равняться единице. Можно задавать фиксированную ширину столбцам.
Ext.create('Ext.panel.Panel', {
 renderTo : Ext.getBody(),
 width : 700,
 height : 400,
 layout : 'column',
 items: [
 {
  xtype: 'panel',
  title: 'Panel 1',
  columnWidth: 0.4,
  height: 400,
 },
 {
  xtype: 'panel',
  title: 'Panel 2',
  columnWidth: 0.6,
  layout: 'center',
  height: 400,
  items: [
   {
    xtype: 'button',
    text: 'Click Me'
   }
  ]
 },
 {
  xtype: 'panel',
  title: 'Panel 3',
  width: 150,
  height: 400,
 }
 ]
});

Ext.container.Container есть метод updateLayout, который можно использовать для перепозиционирования дочерних компонентов в соответствии с правилами лейаута. В основном нет необходимости его вызывать, кроме некоторых случаях. Метод updateLayout вызывается при изменении размеров и при добавлении/удалении дочерних компонентов.

Иногда нужно приостановить лейаут, например при последовательном добавлении множества дочерних компонентов. В таких случая надо установить свойству suspendLayout значение true. После добавления или удаления компонентов надо установить значение false и вызвать updateLayout. Также приостановить лейаут полностью для всего фреймворка методом Ext.suspendLayouts() и после пакетного обновления возобновить его методом Ext.resumeLayouts(true).

В Ext JS доступны следующие лейауты:
  • absolute
  • accordion
  • anchor
  • border
  • card
  • center
  • column
  • fit
  • hbox
  • table
  • vbox

absolute

Лейаут определяет абсолютное позиционирование через x и y свойства.
Ext.create('Ext.panel.Panel', {
 renderTo : Ext.getBody(),
 width : 700,
 height : 400,
 layout : 'absolute',
 items: [
 {
 xtype: 'panel',
 title: 'Panel 1',
 x: 12,
 y: 20,
 height: 250,
 },
 {
 xtype: 'panel',
 title: 'Panel 2',
 x: 200,
 y: 150,
 height: 200,
 },
 {
 xtype: 'panel',
 title: 'Panel 3',
 x: 400,
 y: 250,
 width: 150,
 height: 100,
 }
 ]
});

accordion

Лейаут показывает только одну дочернюю панель и поддерживает сворачивание и развертывание панелей.
Ext.create('Ext.panel.Panel', {
 renderTo : Ext.getBody(),
 width : 700,
 height : 400,
 layout : 'accordion',
 items: [
 {
 title: 'Item 1',
 html: 'Lorem ipsum dolor sit amet, consectetur adipiscing
elit,
sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Ut
enim ad minim veniam, quis nostrud exercitation ullamco laboris
nisi
ut aliquip ex ea commodo consequat. Duis aute irure dolor in
reprehenderit in voluptate velit esse cillum dolore eu fugiat
nulla
pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
culpa qui officia deserunt mollit anim id est laborum'
 },
 {
 title: 'Item 2',
 html: 'some content here'
 },
 {
 title: 'Item 3',
 html: 'empty'
 }
 ]
});

anchor

Лейаут позволяет задавать размеры дочерних компонентов относительно контейнера. При изменении размера контейнера все дочерние компоненты также меняют свой размер в соответствии с правилами лейаута.
Ext.create('Ext.panel.Panel', {
 renderTo : Ext.getBody(),
 width : 700,
 height : 400,
 layout : 'anchor',
 items: [
 {
 title: 'Item 1',
 html: 'Item 1',
 anchor: '50%'
 },
 {
 title: 'Item 2',
 html: 'Item 2',
 anchor: '-20 -200'
 },
 {
 title: 'Item 3',
 html: 'Item 3',
 anchor: '-200'
 }
 ]
});

border

Лейаут позволяет позиционировать дочерние элементы в терминах регионов: центр, север, юг, восток, запад. При использовании этого лейаута надо всегда иметь один компонент по центру.
Ext.create('Ext.panel.Panel', {
 renderTo : Ext.getBody(),
 width : 700,
 height : 400,
 layout : 'border',
 items: [
 {
 title: 'Item 1',
 html: 'Item 1',
 region: 'center'
 },
 {
 title: 'Item 2',
 html: 'Item 2',
 region: 'east',
 width: 200
 },
 {
 title: 'Item 3',
 html: 'Item 3',
 region: 'south',
 height: 100
 }
 ]
});

card

В этом лейауте виден только один компонент. Лейаут используется для мастеров и вкладок.
Ext.create('Ext.panel.Panel', {
 renderTo : Ext.getBody(),
 width : 700,
 height : 400,
 layout : 'card',
 defaultListenerScope: true,
 bbar: ['->',
 {
 itemId: 'btn-prev',
 text: 'Previous',
 handler: 'showPrevious',
 disabled: true
 },
 {
 itemId: 'btn-next',
 text: 'Next',
 handler: 'showNext'
 }
 ],
 items: [
 {
 index: 0,
 title: 'Item 1',
 html: 'Item 1'
 },
 {
 index: 1,
 title: 'Item 2',
 html: 'Item 2'
 },
 {
 index:2,
 title: 'Item 3',
 html: 'Item 3'
 }
 ],
 showNext: function () {
 this.navigate(1);
 },
 showPrevious: function () {
 this.navigate(-1);
 },
 navigate: function (incr) {
 var layout = this.getLayout();
 var index = layout.activeItem.index + incr;
 layout.setActiveItem(index);

 this.down('#btn-prev').setDisabled(index===0);
 this.down('#btn-next').setDisabled(index===2);
 }
});

center

Лейаут размещает дочерний компонент по центру. В начале раздела про лейауты я уже приводил пример такого лейаута.

column

С помощью этого лейаута можно разбить контейнер на столбцы заданного размера и разместить в этих столбцах дочерние компоненты. Пример также приводился выше по тексту.

fit

В этом лейауте дочерний компонент заполняет собой весь контейнер.
Ext.create('Ext.panel.Panel', {
 renderTo : Ext.getBody(),
 width : 700,
 height : 400,
 layout : 'fit',
 bodyPadding: 20,
 items: [
 {
 title: 'Item 1',
 html: 'Fills the container',
 }
 ]
});
Интервал между родительским и дочерним компонентом задается свойством bodyPadding.

hbox

Этот лейаут похож на column, но еще позволяет растягивать высоту столбцов. Опция flex позволяет дочернему компоненту изгибаться горизонтально в соответствии с заданным относительно flex значением.
Ext.create('Ext.panel.Panel', {
 renderTo : Ext.getBody(),
 width : 700,
 height : 400,
 layout :
 {
 type: 'hbox',
 pack: 'start',
 align: 'stretch',
 },
 items: [
 {
 title: 'Item 1',
 html: 'Item 1',
 flex: 1
 },
 {
 title: 'Item 2',
 html: 'Item 2',
 width: 100
 },
 {
 title: 'Item 3',
 html: 'Item 3',
 flex: 2
 }
 ]
});

table

Лейаут в формате таблицы. Можно задать количество столбцов и строк через свойства rowspan и colspan.
Ext.create('Ext.panel.Panel', {
 renderTo : Ext.getBody(),
 width : 700,
 height : 400,
 layout :
 {
 type: 'table',
 columns: 3,
 tableAttrs: {
 style: {
 width: '100%'
 }
 }
 },
 items: [
 {
 rowspan: 3,
 title: 'Item 1',
 html: 'Item 1'
 },
 {
 title: 'Item 2',
 html: 'Item 2'
 },
 {
 title: 'Item 3',
 rowspan: 2,
 html: 'Item 3'
 },
 {
 title: 'Item 4',
 html: 'Item 4'
 },
 {
 title: 'Item 5',
 html: 'Item 5'
 },
 {
 title: 'Item 6',
 html: 'Item 6'
 },
 {
 title: 'Item 7',
 html: 'Item 7'
 }
 ]
});

VBox

Лейаут размещает дочерние компоненты вертикально по направлению вниз один за другим.
Ext.create('Ext.panel.Panel', {
 renderTo : Ext.getBody(),
 width : 700,
 height : 400,
 layout :
 {
 type: 'vbox',
 pack: 'start',
 align: 'stretch',
 },
 items: [
 {
 title: 'Item 1',
 html: 'Item 1',
 flex: 1
 },
 {
 title: 'Item 2',
 html: 'Item 2',
 height: 100
 },
 {
 title: 'Item 3',
 html: 'Item 3',
 flex: 2
 }
 ]
});