После получения модели и рендеринга представления, виджету необходимо сформировать ссылки на элементы, из которых строится представление. Такие элементы можно разделить на две группы:

  • Элементы - части представления, неотделимые от виджета
<!-- Виджет search -->
<form class="search">
  <!-- Элемент input -->
  <input type="text" class="search__input"/>
  <!-- Элемент button -->
  <input type="button" class="search__button" value="Найти"/>
</form>
  • Вложенные виджеты - другие виджеты, являющиеся частью данного
<!-- Виджет search -->
<form class="search">
  <!-- Виджет input -->
  <input type="text" class="input"/>
  <!-- Элемент button -->
  <input type="button" class="search__button" value="Найти"/>
</form>

Для идентификации элементов виджета я рекомендую использовать БЭМ методологию, так как это стандартизирует именование виджетов и его элементов, а так же упрощает работу с ними.

Формирование ссылок на элементы виджета

Часто виджету необходимо получить доступ к своим элементам (для добавления обработчиков событий, на пример). Сделать это можно двумя способами:

  • Получать ссылку в месте ее использования
function SearchWidget(model, el){
  // Инициализация виджета
}

SearchWidget.prototype.onButtonClick = function(){
  var $input = $(this.el).find('.search__input'); // Получение ссылки

  var search = $input.val(); // Использование ссылки
  ...
}
  • Получить ссылку заранее
function SearchWidget(model, el){
  // Инициализация виджета

  // Получение ссылок
  this.$input = $(this.el).find('.search__input');
}

SearchWidget.prototype.onButtonClick = function(){
  var search = this.$input.val(); // Использование ссылки
  ...
}

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

function SearchWidget(model, el){
  // Инициализация виджета

  // Декларация зависимостей
  this.parts = {
    '$input': '.search__input'
  };
}

// Получение элементов виджета по декларации
SearchWidget.prototype.getParts = function(){
  for(var prop in this.parts){
    this[prop] = $(this.el).find(this.parts[prop]);
  }
};

В случае необходимости, можно использовать оба подхода, заменяя ссылки динамически:

function SearchWidget(model, el){
  // Инициализация виджета

  // Декларация зависимостей
  this.parts = {
    '$input': '.search__input'
  };
}

// Метод заменяющий поле ввода виджета
SearchWidget.prototype.otherMethod = function(){
  this.$input.remove();
  this.$input = $('<input type="text" class="search__input"/>');
  $(this.el).append(this.$input);
};

Корневой элемент виджета можно обернуть в JQuery, что упростит работу с ним в будущем:

function SearchWidget(model, el){
  // Инициализация виджета
  this.el = el;
  this.$el = $(el);
}

Работа с вложенными виджетами

Если элементом виджета является другой виджет, следует рассматривать две основные задачи:

  1. Как рендерить вложенный виджет при рендеринге основного?
  2. Как взаимодействовать с вложенным виджетом?

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

Так, для рендеринга вложенных виджетов лучше использовать их метод render:

SearchWidget.prototype.render = function(){
  var $box = $('<form class="search">');
  
  // Рендеринг и вставка вложенного виджета
  var inputWidget = new InputWidget;
  $box.append(inputWidget.render());

  $box.append('<input type="button" class="search__button" value="Найти"/>');

  return $box;
};

А вот пример взаимодействия с вложенным виджетом:

SearchWidget.prototype.onButtonClick = function(){
  // Получение ссылки на виджет
  var inputWidget = $(this.el).find('.input').data('widget');
  var search = inputWidget.getValue();

  // Использование данных, полученных из виджета
};