Разработка контролов

Hello world

На Wasaby можно достаточно быстро и легко научиться разрабатывать, потому что наш фреймворк строится на базовых принципах HTML, CSS и JavaScript. Посмотрите на демо-пример:

На его основе можно создать собственный и модифицировать в процессе тестирования заявленных возможностей.

Файловая структура примера:

  • Demo — папка с исходными файлами контрола;
    • Template.wml — шаблон контрола;
    • Module.js — модуль контрола;
  • index.html — тестовая веб-страница, на которую подключено ядро Wasaby (wasaby.min.js).

Инициализация контрола и его вставка на страницу выполнена следующим скриптом:

<script>
   require(["Core/Control", "Demo/Module"], function(Control, Module) {
      Control.createControl(Module, {
         element: document.querySelector("#mainContainer")
      }, element);
   });
</script>

Декларативное отображение

Чтобы отобразить данные на странице, достаточно указать в каком месте шаблона их следует поместить.

<!-- WML -->
<div title="{{ text }}">
   {{ text }}
</div>
// JavaScript
define("Demo/Module", ["UI/Base", "wml!Demo/Template"], function(Base, template) {
   var ModuleClass = Base.Control.extend({
      _template: template,
      text: "Hello Wasaby!"
   });
   return ModuleClass;
});

Результат. При наведении курсора на строку отобразится подсказка.

Hello Wasaby!

Демо-пример:

Как видно из примера, данные можно вставлять в содержимое тега и в его атрибуты. Более того, теперь они реактивно связаны с DOM. Как это проверить? Откройте страничку демо-примера в отдельной вкладке. Затем выполните в консоли разработчика следующий код:

document.querySelector('#mainContainer').controlNodes[0].control.text = 'Hello world!'

Так мы изменяем значение переменной text, и оно сразу автоматически обновляется на странице.

Условия и циклы

Для управления присутствием элемента в DOM мы используем директиву <ws:if>, что продемонстрировано в следующем примере.

<!-- WML -->
<div>
   <ws:if data="{{ isVisible }}">
      Message is visible.
   </ws:if>
   <ws:else>
      Message is hidden.
   </ws:else>
</div>
// JavaScript
define("Demo/Module", ["UI/Base", "wml!Demo/Template"], function(Base, template) {
   var ModuleClass = Base.Control.extend({
      _template: template,
      isVisible: true
   });
   return ModuleClass;
});

Результат:

Message is visible.

Демо-пример:

Для многократного добавления элемента мы используем директиву <ws:for>, как это показано в примере ниже.

<!-- WML -->
<ul>
    <ws:for data="key, value in list">
        <li>{{ value }}</li>
    </ws:for>
</ul>
// JavaScript
define("Demo/Module", ["UI/Base", "wml!Demo/Template"], function(Control, template) {
   var ModuleClass = Base.Control.extend({
      _template: template,
      _beforeMount: function() {
         this.list = ["Messages", "Chats", "Groups"];
      }
   });
   return ModuleClass;
});

Результат:

* Messages
* Chats
* Groups

Демо-пример:

В примере мы впервые использовали метод _beforeMount(), где объявили переменную. А последующих разделах мы подробнее поговорим о назначении метода.

Обработка событий

Для создания интерактивных приложений мы можем реагировать на действия пользователя, например, клик по кнопке. В следующем примере показано, как мы можем отследить и обработать событие click для DOM элемента.

В следующем примере в обработчике описана только логика обработки, а сама работа с DOM выполняется автоматически ядром Wasaby.

<!-- WML -->
<div>
    Counter: <button on:click="clickHandler()">{{ count }}</button>
</div>
// JavaScript
define("Demo/Module", ["UI/Base", "wml!Demo/Template"], function(Base, template) {
   var ModuleClass = Base.Control.extend({
      _template: template,
      count: 0,
      clickHandler: function() {
         this.count++;
      }
   });
   return ModuleClass;
});

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

Демо-пример:

В следующем примере показана обработка пользовательского ввода.

<!-- WML -->
<div>
    <p>Input your name: <input type="text" on:input="inputHandler()"/></p>
    <p>Your name is {{ name }}</p>
</div>
// JavaScript
define("Demo/Module", ["UI/Base", "wml!Demo/Template"], function(Base, template) {
   var ModuleClass = Base.Control.extend({
      _template: template,
      inputHandler: function(event) {
         this.name = event.target.value;
      }
   });
   return ModuleClass;
});

Результат: когда пользователь вводит символ в поле ввода, они сразу же отображаются в строке ниже.

Демо-пример:

Приложение как набор контролов

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

Контрол — это изолированная часть функционала. С точки зрения файловой структуры, это минимум два файла: JS-модуль, где описана логика, и WML-шаблон, где описано представление контрола.

Ниже показан пример контрола-спойлера:

<!-- WML -->
<div>
    <button on:click="clickHandler()">show more</button>
    <ws:if data="{{ showSpoiler }}">
        <p style="border: 1px solid #ccc">{{ _options.description }}</p>
    </ws:if>
</div>
// JavaScript
define("Spoiler/Module", ["UI/Base", "wml!Spoiler/Template"], function(Base, template) {
   var ModuleClass = Base.Control.extend({
      _template: template,
      showSpoiler: false,
      clickHandler: function() {
         this.showSpoiler = !this.showSpoiler;
      }
   });
   return ModuleClass;
});

Теперь его можно переиспользовать в другом контроле. Давайте сделаем это:

<!-- WML -->
<div>
    Click on the button to display additional text.
    <Spoiler.Module description="{{ text }}" />
</div>
// JavaScript
define("Demo/Module", ["UI/Base", "wml!Demo/Template"], function(Base, template) {
   var ModuleClass = Base.Control.extend({
      _template: template,
      text: "This text was hidden by spoiler, but now it is visible. You can click again to hide this text."
   });
   return ModuleClass;
});

Демо-пример:

В примере показано, что родительский контрол Demo/Module передаёт данные в дочерний контрол-спойлер.

Узнать больше

Выше мы кратко представили основные возможности Wasaby Framework. Подробнее о разработке контролов вы можете прочитать в разделах: