- PVSM.RU - https://www.pvsm.ru -

Создаем собственные виджеты в Dojo

Создаем собственные виджеты в Dojo - 1
Dojo Toolkit это одновременно самый мощный и наименее используемый JavaScript фреймворк. Dojo состоит из AMD модулей, большая часть которых является виджетами. Виджеты обычно состоят из логики на JavaScript и HTML шаблона. В будущей версии 2.0 заявлена поддержка WebComponents. Dojo позволяет легко как создать полностью новый виджет, так и расширить или изменить уже существующий. В этом посте я расскажу как это делать.

Создание простейшего виджета

Для начала создадим простейший виджет.

Step 1: Создание структуры

Для объявления своего виджета нужно создать JavaScript файл со следующим содержанием:

define([
      "dojo/_base/declare",
      "dijit/_Widget",
      "dijit/_TemplatedMixin"
], function(declare, _Widget, _TemplatedMixin){
  return declare([_Widget, _TemplatedMixin], {});
});

Пока мы просто объявили AMD модуль и указали несколько зависимостей. Первым аргументом функции declare является массив модулей от которых требуется унаследовать создаваемый модуль. Сейчас указано, что модуль наследует базовый для всех виджетов модуль dijit/_Widget и модуль _TemplatedMixin, который предоставляет шаблонизатор.

Step 2: Создание HTML представления

Создадим рядом с файлом модуля папку templates и в ней HTML файл. Назвать его лучше так же как и файл модуля. Пусть модуль называтся MyCustomWidget.js, тогда файл шаблона следует назвать MyCustomWidget.html. В файле шаблона должно находится HTML представление виджета. Причем корень обязательно должен быть один.

Шаблонизатор позволяет:

  • указать специальные узлы, attachPoints, которые будут доступны как свойства виджета;

    Для этого у нужного узла необходимо задать специальный атрибут: data-dojo-attach-point=”customNode”, где “customNode” — название свойства виджета через которое будет доступен узел. Корневой узел виджета всегда доступен через свойство domNode.

  • определить обработчики событий;

    Для этого у нужного узла необходимо задать специальный атрибут: data-dojo-attach-event=”ondijitclick:_onClick”, где “ondijitclick” указывает на событие, которое необходимо обрабатывать, в данном случае клик, а “_onClick” — название метода, который должен выступить в роли обработчика события.

  • указать место подстановки значений свойств виджета при его создании.

    Для этого в шаблоне нужно написать ${nameProp}, где “nameProp” — название свойства.

Step 3: Связываем шаблон и данные

Подключим шаблон:

define([
      "dojo/_base/declare",
      "dijit/_Widget",
      "dijit/_TemplatedMixin",
      "dojo/text!./templates/MyCustomWidget.html"
], function(declare, _Widget, _TemplatedMixin, template){
  return declare([_Widget, _TemplatedMixin], {
      templateString: template
  });
});

На самом деле мы могли и не выносить шаблон в отдельный файл, а сразу задать HTML как значение свойства templateString или вынести его в переменную, но, по-моему, это снижает красоту кода.

В качестве примера виджета создадим виджет выводящий фамилию и имя.

<div>
      <span data-dojo-attach-point="surnameNode">${surname}</span>
       
      <span data-dojo-attach-point="nameNode">${name}</span>
</div>

Чтобы каждый раз, когда у виджета изменяются свойства, менялись значения и в HTML, необходимо связать сеттеры свойств и attachPoints. Можно указать какое свойство какого attachPoint соответствует какому свойству виджета, а можно определить собственные сеттеры.

Если у вас есть свойство, где задание/получение значения сложнее чем просто обращение к свойству объекта, то вам нужно определить собственные сеттеры/геттеры соблюдая простые правила именования: для свойства “foo” это будут _setFooAttr/_getFooAttr. Методы set и get автоматически найдут их и вызовут в случае необходимости.

define([
      "dojo/_base/declare",
      "dijit/_Widget",
      "dijit/_TemplatedMixin",
      "dojo/text!./templates/MyCustomWidget.html"
], function(declare, _Widget, _TemplatedMixin, template){
  return declare([_Widget, _TemplatedMixin], {
      templateString: template,
      _setSurnameAttr: { node: "surnameNode", type: "innerHTML" },
      _setNameAttr: function(val){
              this.nameNode.innerHTML = val;
              this._set("name", val);
      }
  });
});

Как вы, наверно, уже могли догадаться, описанный виджет можно подключить используя его имя и расположение. Можно использовать прямой путь до JS-файла модуля, а можно объявить свой пакет, по аналогии с dojo, dijit и dojox, и подключать файлы из него. Альтернативой является сразу использовать результат вызова функции declare.

Как работает созданный нами код можно посмотреть здесь [1].

Виджет состоящий из других виджетов

Виджет может состоять из других виджетов. Составляющие виджеты можно добавить динамически во время создания виджета, но удобнее объявить их сразу в шаблоне. Для этого к модулям от которых наследуется виджет необходимо добавить dijit/_WidgetsInTemplateMixin.

В качестве примера шаблона рассмотрим фрагмент шаблона слайдера, который состоит из горизонтального ползунка и текстового поля ввода:

Создаем собственные виджеты в Dojo - 2

<div>
	<div>
		<div dojoType="dijit/form/HorizontalSlider"
			data-dojo-attach-point="slider"
			name="${name}"
			value="${value}"
			maximum="${maximum}"
			minimum="${minimum}"
			step="${step}"
			showButtons="${showButtons}"
			intermediateChanges="${intermediateChanges}"
			style="width:150px">
		</div>
		<div dojoType="dijit/form/TextBox"
			value="${value}"
			type="number"
			data-dojo-attach-point="textbox">
		</div>
		<span data-dojo-attach-point="legendNode"></span>
	</div>
	<div data-dojo-attach-point="descriptionNode"></div>
</div>

В этом фрагменте мы объявили виджет dijit/form/HorizontalSlider, который представляет собой горизонтальный ползунок, и виджет dijit/form/TextBox — текстовое поле ввода.

Все виджеты сразу вписаны в специальную разметку и обладают:

  • свойствами с фиксированными значениями;
  • свойствами, значения которых проброшены из виджета слайдера.

Также, мы снабдили вложенные виджеты атрибутами data-dojo-attach-point, чтобы можно было обращаться к ним, как к свойствам виджета. Т.е. если мы захотим получить значение поля ввода, то нам нужно написать:

this.textbox.get("value");

Аналогичный виджет из APS JS SDK [2] можно увидеть в APS Fiddle [3].

Жизненный цикл виджета

Жизненний цикл виджета позволяет понять что именно и когда происходит.
Создаем собственные виджеты в Dojo - 3
Вы можете расширить или переопределить следующие методы:

  • constructor

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

  • параметры создания виджета смешиваются со значением свойств по умолчанию

    Данное действие нельзя переопределить, но важно знать когда это происходит.

  • postMixInProperties

    Данный метод вызывается перед тем как будет создано HTML представление виджета. Если нужно добавить или изменить свойства экземпляра виджета перед созданием его визуального представления — это лучшее место чтобы сделать это.

  • buildRendering

    dijit/_Templated предоставляет реализацию buildRendering, которой достаточно в большинстве случаев: загрузит и прочитает шаблон, создаст DOMElements, привяжет специальные узлы и события. Итоговый результат будет помещен в this.domNode. Если вы не используете dijit/_Templated, например, используете другой шаблонизатор, тогда это то место, где вы должны его использовать.

  • вызываются сеттеры

    Вызываются сеттеры для свойств, значения которых были заданы при создании экземпляра виджета или не пусты по умолчанию.

  • postCreate

    Основное место для дополнительной логики при создании виджета. Но, следует помнить, что в случае контейнерного виджета дочерние (не те, что объявлены в шаблоне) виджеты еще не добавлены и HTML представление еще не помещено в DOM.

  • startup

    Разбор и создание всех дочерних виджетов завершено. Виджет помещен в DOM.

  • destroy

    Реализуйте destroy, если вам нужно выполнить какие-то дополнительные действия при уничтожении виджета.

Inherited

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

postCreate: function(){
   // do my stuff, then...
   this.inherited(arguments);
}

Полезные ссылки

Еще пример создания виджета [4].
Больше информации о создании виджетов. [5]
Больше информации о жизненном цикле виджета. [6]

Автор: BuranLcme

Источник [7]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/javascript/74759

Ссылки в тексте:

[1] здесь: http://jsfiddle.net/burashka/ou66ugqn/

[2] APS JS SDK: http://habrahabr.ru/company/parallels/blog/202022/

[3] APS Fiddle: http://cdn.apsstandard.org/apsfiddle/?file=_static/examples/slider/loadSlider.html

[4] Еще пример создания виджета: http://dojotoolkit.org/documentation/tutorials/1.10/recipes/custom_widget/

[5] Больше информации о создании виджетов.: http://dojotoolkit.org/reference-guide/1.10/quickstart/writingWidgets.html

[6] Больше информации о жизненном цикле виджета.: http://dojotoolkit.org/reference-guide/1.10/dijit/_WidgetBase.html

[7] Источник: http://habrahabr.ru/post/240779/