После получения модели и рендеринга представления, виджету необходимо сформировать ссылки на элементы, из которых строится представление. Такие элементы можно разделить на две группы:
- Элементы - части представления, неотделимые от виджета
<!-- Виджет 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);
}
Работа с вложенными виджетами
Если элементом виджета является другой виджет, следует рассматривать две основные задачи:
- Как рендерить вложенный виджет при рендеринге основного?
- Как взаимодействовать с вложенным виджетом?
Для сохранения независимости и переносимости виджетов, рекомендуется взаимодействовать с ними через открытые интерфейсы и события.
Так, для рендеринга вложенных виджетов лучше использовать их метод 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();
// Использование данных, полученных из виджета
};