В этом посте вы узнаете о новой фиче 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).
