События Marionette
Система событий Marionette предоставляет механизм для взаимодействия объектов друг с другом единообразным способом. В Marionette это подразумевает, что один объект вызывает событие, на которое другой подписывается. Это расширение системы обработки событий Backbone, и отличается от событий DOM. Оно интегрировано в каждый класс Marionette.
Индекс документации
Вызов и прослушивание событий
В Marionette полностью поддерживается традиционная система обработки событий из Backbone. Однако Marionette предоставляет дополнительный API событий, использующий метод triggerMethod. Ключевое различие между ними заключается в том, что triggerMethod автоматически вызывает обработчики событий со специальными именами.
triggerMethod
Так же, как метод trigger из Backbone, метод triggerMethod вызывает событие с указанным именем на экземпляре. Все слушатели будут затем вызваны на событии. Если слушателей нет, вызов всё равно будет успешным. Все аргументы после первой строки имени события будут переданы всем обработчикам событий.
import { View } from 'backbone.marionette';
const MyView = View.extend({
callMethod(myString) {
console.log(myString + ' was passed');
}
});
const myView = new MyView();
/* See Backbone.listenTo */
myView.on('something:happened', myView.callMethod);
/* Calls callMethod('foo'); */
myView.triggerMethod('something:happened', 'foo');
Метод triggerMethod доступен для всех классов Marionette.
Прослушивание событий
Триггеры событий Marionette работают так же, как и обычные события Backbone - можно использовать myView.on и myObject.listenTo для реагирования на события:
import { View } from 'backbone.marionette';
const MyView = View.extend({
initialize() {
this.on('event:happened', this.logCall);
},
logCall(myVal) {
console.log(myVal);
}
});
Также можно использовать listenTo как в Backbone:
import { View } from 'backbone.marionette';
const OtherView = View.extend({
initialize(someView) {
this.listenTo(someView, 'event:happened', this.logCall);
},
logCall(myVal) {
console.log(myVal);
}
});
const MyView = View.extend();
const myView = new MyView();
const otherView = new OtherView(myView);
myView.triggerMethod('event:happened', 'someValue'); // Logs 'someValue'
Как и в Backbone, listenTo передаёт объект, на котором оно вызвано, в качестве переменной контекста. Они ведут себя точно так же, как в Backbone, поэтому использование object.on потребует от вас самостоятельного отключения обработчиков событий для предотвращения утечек памяти. Однако Marionette предоставляет дополнительные вспомогательные средства в рамках жизненного цикла представления, которые связывают и отключают обработчики событий за вас. В этом и заключается суть onEvent Связывания.
onEvent Связывание
Главное различие между Backbone.trigger и triggerMethod заключается в том, что triggerMethod может вызывать события со специальными именами на экземпляре. Например, представление, которое было отображено, внутренне вызывает view.triggerMethod('render') и вызывает onRender, что удобно для добавления поведения в ваши представления.
Определение того, какой метод будет вызван событием, просто, мы проиллюстрируем это на примере с before:dom:refresh, но это также работает с любыми пользовательскими событиями, которые вы хотите вызвать:
- Разделить слова вокруг символов
:- например,before,dom,refresh - Прописать заглавную букву каждого слова -
Before,Dom,Refresh - Добавить ведущий
on-on,Before,Dom,Refresh - Объединить в один вызов -
onBeforeDomRefresh
Следуя этому процессу, before:dom:refresh вызовет метод onBeforeDomRefresh. Посмотрим, как это работает на примере пользовательского события:
import { View } from 'backbone.marionette';
const MyView = View.extend({
onMyEvent(myVal) {
console.log(myVal);
}
});
const myView = new MyView();
myView.triggerMethod('my:event', 'someValue'); // Logs 'someValue'
Как и прежде, все аргументы, передаваемые в triggerMethod после имени события, попадут в обработчик события. Это гарантирует отсутствие неожиданных утечек памяти.
События events и triggers представления
Представления могут автоматически привязывать события DOM к методам и события представления с помощью events и triggers соответственно:
import { View } from 'backbone.marionette';
const MyView = View.extend({
events: {
'click a': 'showModal'
},
triggers: {
'keyup input': 'data:entered'
},
showModal(event) {
console.log('Show the modal');
},
onDataEntered(view, event) {
console.log('Data was entered');
}
});
Дополнительную информацию см. в документации по взаимодействиям с DOM.
События сущности представления
Представления могут автоматически подписываться на события своего модели или коллекции с помощью modelEvents и collectionEvents соответственно.
import { View } from 'backbone.marionette';
const MyView = View.extend({
modelEvents: {
'change:someattribute': 'onChangeSomeattribute'
},
collectionEvents: {
'update': 'onCollectionUpdate'
},
onChangeSomeattribute() {
console.log('someattribute was changed');
},
onCollectionUpdate() {
console.log('models were added or removed in the collection');
}
});
Дополнительную информацию см. в документации по событиям сущностей.
События дочерних представлений
View и CollectionView могут отслеживать и реагировать на события любых их непосредственных дочерних элементов. Любые события, вызванные в представлении, также автоматически передаются их непосредственным родительским представлениям. Посмотрим на быстрый пример:
import { View, CollectionView } from 'backbone.marionette';
const Item = View.extend({
tagName: 'li',
triggers: {
'click a': 'select:item'
}
});
const Collection = CollectionView.extend({
tagName: 'ul',
childViewEvents: {
'select:item': 'itemSelected'
},
itemSelected(childView) {
console.log('item selected: ' + childView.model.id);
}
});
Передача событий
События, вызванные в представлении, передаются вверх к их непосредственным родительским представлениям, вызывая методы событий с префиксом childview: (более подробно об этом чуть ниже) и любые методы, привязанные к атрибуту childViewEvents. Это работает для встроенных событий, пользовательских событий, вызванных с помощью triggerMethod, и связанных событий с помощью triggers.
ПРИМЕЧАНИЕ Автоматическая передача событий может быть отключена путем установки childViewEventPrefix в false.
При использовании неявных слушателей используется префикс события childview:*, который должен быть включён в обработчик:
import { View, } from 'backbone.marionette';
const MyView = View.extend({
triggers: {
click: 'click:view'
},
doSomething() {
this.triggerMethod('did:something', this);
}
});
const ParentView = View.extend({
regions: {
foo: '.foo-hook'
},
onRender() {
this.showChildView('foo', new MyView());
},
onChildviewClickView(childView) {
console.log('View clicked ' + childView);
},
onChildviewDidSomething(childView) {
console.log('Something was done to ' + childView);
}
})
ПРИМЕЧАНИЕ triggers автоматически передаёт дочернее представление в качестве аргумента родительскому представлению, однако triggerMethod не делает этого. Обратите внимание, что в приведенном выше примере triggerMethod явно передаёт дочернее представление.
Использование CollectionView
Это работает точно так же для CollectionView и его childView.
import { View, CollectionView } from 'backbone.marionette';
const MyChild = View.extend({
triggers: {
click: 'click:child'
}
});
const MyList = CollectionView.extend({
onChildviewClickChild(childView) {
console.log('Childview ' + childView + ' was clicked');
}
});
Префикс события дочернего представления
Вы можете настроить префикс события для событий, передаваемых через представление. Для этого установите childViewEventPrefix в представлении или collectionview. Дополнительную информацию о childViewEventPrefix см. в разделе Передача событий.
Значение по умолчанию для childViewEventPrefix равно childview. Установка этого свойства в false отключит автоматическую передачу событий.
import Backbone from 'backbone';
import { CollectionView } from 'backbone.marionette';
import MyChildView from './my-child-view';
const myCollection = new Backbone.Collection([{}]);
const CollectionView = CollectionView.extend({
childViewEventPrefix: 'some:prefix',
childView: MyChildView
});
const collectionView = new CollectionView({
collection: myCollection
});
collectionView.on('some:prefix:render', function(){
// child view was rendered
});
collectionView.render();
childViewEventPrefix может быть предоставлен в определении представления или в вызове конструктора для получения экземпляра представления.
Явные обработчики событий
Для вызова определённых функций при вызове триггеров событий используйте атрибут childViewEvents для сопоставления событий дочерних представлений с методами родительского представления. Это касается событий, вызванных в дочерних представлениях - без префикса childview: - и вызывает метод, к которому ссылается или прикрепленная функция.
import { View } from 'backbone.marionette';
const MyView = View.extend({
triggers: {
click: 'view:clicked'
}
});
const ParentView = View.extend({
regions: {
foo: '.foo-hook'
},
childViewEvents: {
'view:clicked': 'displayMessage'
},
onRender() {
this.showChildView('foo', new MyView());
},
displayMessage(childView) {
console.log('Displaying message for ' + childView);
}
});
Прикрепление функций
Атрибут childViewEvents также может непосредственно прикреплять функции, чтобы сделать их обработчиками событий:
import { View } from 'backbone.marionette';
const MyView = View.extend({
triggers: {
click: 'view:clicked'
}
});
const ParentView = View.extend({
regions: {
foo: '.foo-hook'
},
childViewEvents: {
'view:clicked'(childView) {
console.log('Function called for ' + childView);
}
},
onRender() {
this.showChildView('foo', new MyView());
}
});
Использование CollectionView's childViewEvents
import { CollectionView } from 'backbone.marionette';
// childViewEvents can be specified as a hash...
const MyCollectionView = CollectionView.extend({
childViewEvents: {
// This callback will be called whenever a child is rendered or emits a `render` event
render() {
console.log('A child view has been rendered.');
}
}
});
Вызов событий на дочерних событиях
Хеш-таблица childViewTriggers или метод позволяет перенаправлять события дочерних представлений без ручного настройки привязок. Значения хеша должны быть строкой события, которое нужно вызвать у родителя.
childViewTriggers - это синтаксический сахар поверх childViewEvents, так же, как триггеры представления - это синтаксический сахар поверх событий представления.
import { View, CollectionView } from 'backbone.marionette';
// The child view fires a custom event, `show:message`
const ChildView = View.extend({
// Events hash defines local event handlers that in turn may call `triggerMethod`.
events: {
'click .button': 'onClickButton'
},
triggers: {
'submit form': 'submit:form'
},
onClickButton () {
// Both `trigger` and `triggerMethod` events will be caught by parent.
this.trigger('show:message', 'foo');
this.triggerMethod('show:message', 'bar');
}
});
// The parent uses childViewEvents to catch the child view's custom event
const ParentView = CollectionView.extend({
childView: ChildView,
childViewTriggers: {
'show:message': 'child:show:message',
'submit:form': 'child:submit:form'
},
onChildShowMessage (message) {
console.log('A child view fired show:message with ' + message);
},
onChildSubmitForm (childView) {
console.log('A child view fired submit:form');
}
});
const GrandParentView = View.extend({
regions: {
list: '.list'
},
onRender() {
this.showChildView('list', new ParentView({
collection: this.collection
}));
},
childViewEvents: {
'child:show:message': 'showMessage'
},
showMessage(childView) {
console.log('A child (' + childView + ') fired an event');
}
});
Использование CollectionView's childViewTriggers
import { View, CollectionView } from 'backbone.marionette';
// The child view fires a custom event, `show:message`
const ChildView = View.extend({
// Events hash defines local event handlers that in turn may call `triggerMethod`.
events: {
'click .button': 'onClickButton'
},
// Triggers hash converts DOM events directly to view events catchable on the parent.
// Note that `triggers` automatically pass the first argument as the child view.
triggers: {
'submit form': 'submit:form'
},
onClickButton () {
// Both `trigger` and `triggerMethod` events will be caught by parent.
this.trigger('show:message', 'foo');
this.triggerMethod('show:message', 'bar');
}
});
// The parent uses childViewEvents to catch the child view's custom event
const ParentView = CollectionView.extend({
childView: ChildView,
childViewTriggers: {
'show:message': 'child:show:message',
'submit:form': 'child:submit:form'
},
onChildShowMessage (message) {
console.log('A child view fired show:message with ' + message);
},
onChildSubmitForm (childView) {
console.log('A child view fired submit:form');
}
});
События жизненного цикла
Представления Marionette вызывают события во время создания и уничтожения. Дополнительную информацию см. в документации по View Жизненному циклу.
© 2017 Muted Solutions, LLC
Licensed under the MIT License.
https://marionettejs.com/docs/v4.0.0/events.html