В этом посте вы узнаете о новой фиче Marionette.js — Behaviors.
Очень часто в различных элементах интерфейса у нас встречаются похожие элементы управления (например кнопка «Удалить» может быть и у категорий, и у записей, и в списке зарегистрированных пользователей… да везде), и каждый раз приходится описывать обработчик этой кнопки в каждом View, причем везде одинаково.
Но это уже называется дублирование кода, и не приветствуется в большинстве общества. Поэтому разработчики Marionette.js предоставили нам такую замечательную фичу как Behaviors.
Behaviors предоставляет интерфейс для изолирования описаний взаимодействия DOM с пользователем в отдельные логические куски кода. Behavior может быть применено к любому View любое количество раз.
В этой статье рассмотрим самый тривиальный пример — кнопка «Удалить».
Как описываются Behaviors и где они хранятся?
Для того, что бы пользоваться Behaviors, надо сначала указать Marionette где они хранятся. Это делается так
var Behaviors={};
Backbone.Marionette.Behaviors.behaviorsLookup = function() {
return Behaviors;
}
Вы можете изменить место хранения.
После того, как необходимая настройка проведена, можно приступить к созданию нашего Behavior.
Описание функций
Что бы создать новый шаблон поведения, надо расширить Backbone.Marionette.Behavior.
Behaviors.CloseButton=Backbone.Marionette.Behavior.extend({...})
Чем же можно расширять этот объект? Мы можем слушать события модели или коллекции, привязанной к виду, к которому применен этот шаблон.
Marionette.Behavior.extend({
modelEvents: {
"change:doge": "onDogeChange"
},
onDogeChange: function() {
// buy more doge...
},
collectionEvents: {
add: "onCollectionAdd"
},
onCollectionAdd: function() {
}
});
Из View в Behavior можно передавать options. В них мы можем передать что угодно, к примеру класс элемента, при клике на который надо что-то удалить.
Также можно слушать события вида, к которому мы его применим.
Обратите внимание, что контекст функций здесь будет не вид, к которому применен шаблон, а сам шаблон. Что бы обращаться к виду, вы можете использовать this.view. Также доступны this.$ и this.$el.
Backbone.Marionette.Behavior.extend({
onRender:function(){ // Это событие вида "render".
this.view;// Экземпляр привязанного вида
this.$; // эквивалент this.view.$
this.$el; // эквивалент this.view.$el
this.options; // объект с опциями, переданными из вида.
}
})
Если надо предопределить какие-нибудь опции, делаем так
Marionette.Behavior.extend({
defaults: {
'dominion': 'invasion',
'doge': 'amaze'
}
});
Это работает по аналогии с defaults у моделей.
Создаем Behavior
Как я уже говорил, в качестве примера я буду использовать кнопку удаления. Обратите внимание, что новый шаблон поведения должен быть свойством объекта, указанного нами марионетке как хранилище.
Behaviors.CloseButton=Backbone.Marionette.Behavior.extend({
defaults:{
'el':'.remove-this'
},
onRender:function(){
this.$el.find(this.options.el).on('click',this.close.bind(this));
},
close: function() {
this.view.model.collection.remove(this.view.model);
}
});
Итак, мы создали Behavior, назвали его CloseButton. Что он делает? Он слушает событие Render, и когда оно произошло, вешает обработчик на клик по элементу. А какому именно элементу? Он берет его из options. По умолчанию это элемент с классом .remove-this, то есть такая кнопка вполне сойдет
<button class="remove-this">Удалить</button>
После того, как шаблон заготовлен, можно применять его к View.
var ListItem=Backbone.Marionette.ItemView.extend({
behaviors: {
CloseButton: {
// Сюда передаются options.
// В данном случае они пусты, поэтому Marionette сама подставит в el значение '.remove-this'
}
}
})
var Product=Backbone.Marionette.ItemView.extend({
behaviors: {
CloseButton: {
el:'.delete-product'
}
}
})
В вид Product мы передали Behavior с опцией, которая переопределит элемент для клика.
Вот так с помощью Behaviors мы избежали дублирования кода и сделали мир лучше.
P.S. Если кому-нибудь будет интересно, могу написать о сортировке CollectionView с помощью Drag&Drop (используя jQuery Sortable).