Рано или поздно наступает момент, когда возможностей фреймворка вам недостаточно. "Ах, как же так, забыли такую полезную кнопочку/контрол/приложение сделать..." - сетуете вы. Вот тогда и приходит в голову идея написать нехватающий функционал самому. Точнее дописать. И любой уважающий себя фреймворк предоставляет механизмы для собственного расширения/изменения. ExtJs не стал исключением.
По сути расширение это класс, наследованный от уже существующего в библиотеке и реализующий дополнительный функционал. Представим себе, что нам необходимо реализовать контрол, весьма похожий по своему назначению и функционалу на Ext.Panel, но с небольшим отличием - новая панель всегда должна быть квадратной формы (т.е. ширина всегда должна быть равна ее высоте).
1: SquarePanel = Ext.extend(Ext.Panel, { 2: //Устанавливаем размер панели по умолчанию
3: width: 100,
4: height: 100,
5: onResize: function(width, height) { 6: //Если размеры нашей панели были изменены, причем непропорционально - вернуть ей квадратную форму
7: if (width != height) { 8: this.body.setWidth(height);
9: }
10: //Вызываем базовый метод класса-родителя, т.е. - класса Panel.
11: SquarePanel.superclass.onResize.call(this, height, height);
12: },
13: //Добавляем метод который позволит нам изменять размеры нашей панели, указав лишь размер одной ее стороны
14: setSquareSize(length){ 15: this.body.setWidth(length);
16: this.body.setHeight(length);
17: }
18: });
Вот такая нехитрая конструкция Ext.extend позволяет создать новый класс, с дополнительными возможностями, а именно – новое поведение панели при изменении ее размеров и новый метод setSquareSize позволяющий установить новые размеры панели. Я акцентировал внимание на дополнительных возможностях, потому что все свойства, методы и события базового класса (Ext.Panel) теперь присущи и нашему классу. Если заглянуть внутрь реализации метода extend, то можно увидеть, что
1: //создаем пустую функцию-класс F
2: var F = function(){}, 3: //сюда будет записана ссылка на прототип дочернего класса (т.е. нашего собственного)
4: sbp,
5: //сюда будет записана ссылка на прототип родительского класса
6: spp = sp.prototype;
7: //прототипом класса F становится прототип родительского класса
8: F.prototype = spp;
9: //прототипом нашего же класса становится класс F
10: sbp = sb.prototype = new F();
11: //далее идет переопределение конструктора и назначение суперкласса
12: sbp.constructor=sb;
13: sb.superclass=spp;
14: //...много непонятных буков
Методы и свойства, которые мы переопределили (onResize, width и height) попадут в prototype нашего класса вот таким образом:
1: //sb - это наш класс SquarePanel, а overrrides - объект содержащий дополнения к нашему классу
2: Ext.override(sb, overrides);
О функции override, я расскажу в другой раз. Пока ограничусь лишь кратким описанием – функция Ext.override позволяет замещать функционал уже существующих классов, на ваши собственные реализации.
Далее мы можем расширять нашу панель точно также как и Ext.Panel
1: DifferentSquarePanel = Ext.extend(SquarePanel, {/* some additional logic here */})Что ж, довольно просто и элегантно. Впрочем, как и должно быть в любом уважающем себя фреймворке.