Marionette.CollectionView
CollectionView
будет пробегать по всем моделям в переданной представлению коллекции, отрисовывая каждую модель, используя для этого назначенный childView
.
После этого, присоеденит el
каждого вложенного отрендеренного представления (childView
) к родительскому (collectionView
) el
. По умолчанию,
CollectionView
будет отражать отсортированный порядок коллекции в DOM. Такое поведение можно отключить передачей {sort: false}
при инициализации.
CollectionView расширяется напрямую от Marionette.View
. Подробнее про Marionette.View
можно прочитать тут
the Marionette.View documentation для уточнения информации о доступных свойствах и функциональности.
Дополнительно, взаимодействие с Marionette.Region
будет обеспечивать такие возможности, как кэлбеки onShow
и т.д. Подробнее о регионах
можно прочитать тут the Region documentation
Documentation Index
- CollectionView’s
childView
- CollectionView’s
emptyView
- Callback Methods
- CollectionView Events
- “before:render” event
- “render” event
- “before:reorder” / “reorder” event
- “before:destroy” event
- “destroy” / “destroy:collection” event
- “before:add:child” / “add:child” event
- “before:remove:child event
- “remove:child” event
- “childview:*” event bubbling from child views
- “before:render:collection” event
- “render:collection” event
- CollectionView Child View Events
- CollectionView render
- CollectionView: Automatic Rendering
- CollectionView: Re-render Collection
- CollectionView’s attachHtml
- CollectionView’s resortView
- CollectionView’s viewComparator
- CollectionView’s
filter
- CollectionView’s children
- CollectionView destroy
CollectionView’s childView
Определяет childView
в вашей CollectionView
. Должен быть Backbone.View
определением,т.е. не инстанционированным объектом. Это может быть любой
Backbone.View
или Marionette.ItemView
.
var MyChildView = Marionette.ItemView.extend({});
Marionette.CollectionView.extend({
childView: MyChildView
});
Вложенное представление должно быть определено прежде, чем вы будете на него ссылаться в описании.
Вы можете использовать функцию getChildView
для получения определения класса.
Другой вариант, определить childView
в опциях конструктора.
var MyCollectionView = Marionette.CollectionView.extend({...});
new MyCollectionView({
childView: MyChildView
});
Если не определите childView
, выбросится исключение, указывающее на необходимость определения childView
.
CollectionView’s getChildView
Значение, возвращаемое эти методом - класс ChildView
что будет инстанцирован при рендеренге Model
. Также, этот метод позволяет
настраивать для каждой Model
свой ChildViews
.
var FooBar = Backbone.Model.extend({
defaults: {
isFoo: false
}
});
var FooView = Marionette.ItemView.extend({
template: '#foo-template'
});
var BarView = Marionette.ItemView.extend({
template: '#bar-template'
});
var MyCollectionView = Marionette.CollectionView.extend({
getChildView: function(item) {
// Выбираем класс вложенного представления,
// в зависимости от аттрибута модели 'isFoo'
if (item.get('isFoo')) {
return FooView;
}
else {
return BarView;
}
}
});
var collectionView = new MyCollectionView();
var foo = new FooBar({
isFoo: true
});
var bar = new FooBar({
isFoo: false
});
// Renders a FooView
collectionView.collection.add(foo);
// Renders a BarView
collectionView.collection.add(bar);
CollectionView’s childViewOptions
Существует много сценариев, когда вам необходимо передать информацию от родительсуой collectionView
каждому вложенному
childView
представлению. Для этого добавте определение childViewOptions
в collectionView
(как литеральный объект). Оно
передастся в конструктор childVIew
, как часть options
.
var ChildView = Marionette.ItemView.extend({
initialize: function(options) {
console.log(options.foo); // выведет => "bar"
}
});
var CollectionView = Marionette.CollectionView.extend({
childView: ChildView,
childViewOptions: {
foo: "bar"
}
});
Можно определить childViewOptions
как функцию, если нужно вычеслить значения во время работы приложения. Model
передается внурь функции
и доступна для обращения при вычислениях. Функция должна вернуть объект, аттрибуты объекта будут скопированны в options инстанса
childView
var CollectionView = Marionette.CollectionView.extend({
childViewOptions: function(model, index) {
// проводим какие либо вычесления, model доступна для обращений
return {
foo: "bar",
childIndex: index
}
}
});
CollectionView’s childViewEventPrefix
Вы можете настраивать префикс для событий пересылаемых в collectionView
из вложенных представлений. Для этого, установите childViewEventPrefix
.
Подробнее про события вложенных представлений можно прочитать тут “childview:*” event bubbling from child views
var CV = Marionette.CollectionView.extend({
childViewEventPrefix: "some:prefix"
});
var c = new CV({
collection: myCol
});
c.on("some:prefix:render", function(){
// вложенное представление отрисовано
});
c.render();
childViewEventPrefix
можно передавать в определении класса, либо в опциях вызова констурктора.
CollectionView’s childEvents
Хеш childEvents
или метод (возвращающий хеш) позволяет перехватывать всплывающие childEvents события
без ручных настроек связывания с кэлбэек-функциями. Значения хеша могут быть либо функцией, либо строкой - именем метода в collectionView
.
// childEvents может быть определен как хеш
var MyCollectionView = Marionette.CollectionView.extend({
childEvents: {
// эта кэлбэк-функция будет вызвана вский раз, когда вложенное представление отрисуется или пришлет событие `render`
render: function() {
console.log("a childView has been rendered");
}
}
});
// ... или как функция, возвращающая хеш
var MyCollectionView = Marionette.CollectionView.extend({
childEvents: function() {
return {
render: this.onChildRendered
}
},
onChildRendered: function () {
console.log('A child view has been rendered.');
}
});
Кроме того, childEvents
позволяет перехватывать определенные вами события, присылаемые из вложенных представлений.
Заметьте, что первый аргумент функции будет ссылка на вложенное представление приславшее это событие.
// childView запускает событие `show:message`
var ChildView = Marionette.ItemView.extend({
// в хеше `events` определили локальный обработчик `onClickButton` события клика
events: {
'click .button': 'onClickButton'
},
// хеш triggers позволяет конвертировать DOM события напрямую в события перехватываемые родителем
triggers: {
'submit form': 'submit:form'
},
onClickButton: function () {
// оба `trigger` and `triggerMethod` события будут перехвачены родителем
this.trigger('show:message', 'foo');
this.triggerMethod('show:message', 'bar');
}
});
// родительское представление использует `childEvents` настройки, для обработки событий вложенного представления
var ParentView = Marionette.CollectionView.extend({
childView: ChildView,
childEvents: {
'show:message': 'onChildShowMessage',
'submit:form': 'onChildSubmitForm'
},
onChildShowMessage: function (childView, message) {
console.log('A child view fired show:message with ' + message);
},
onChildSubmitForm: function (childView) {
console.log('A child view fired submit:form');
}
});
CollectionView’s buildChildView
Когда требуется кастомная childView
, нужно переопределить buildChildView
метод. Этот метод принимает 3 параметра и
возращает view instance
, который будет использован для отображения вложенных представлений.
buildChildView: function(child, ChildViewClass, childViewOptions){
// создаем список опций для `childView` класса
var options = _.extend({model: child}, childViewOptions);
//инстанцируем класс представления
var view = new ChildViewClass(options);
// возращаем его
return view;
},
CollectionView’s addChild
Метод addChild
отвечает за рендеринг childViews
и добавления в HTML collectionView
представления. Также, он отвечает за
передачу событий от ChildView
. Чаще всего, вам не нужно его переопределять. Но, если хотите, то можно. Примерно так:
Marionette.CollectionView.extend({
addChild: function(child, ChildView, index){
if (child.shouldBeShown()) {
Marionette.CollectionView.prototype.addChild.apply(this, arguments);
}
}
});
CollectionView’s reorderOnSort
Эта опция полезна, когда вы выполняете пересортировку вашей коллекции. Без этой опции, ваш CollectionView
будет полностью
перерендерен, что может быть очень накладно, в случае большого количества элементов или из-за сложности ваших ChildView
.
Если эта опция активна, то пересортировка Collection
не будет требовать перерисовки, а произойдет только переупорядочивание DOM узлов.
Это может быть проблемой, если ChildView
используют свой индекс в коллекции для рендеринга. В этом случае, вы не сможете
использовать эту опцию, так как вам придется перерендерить каждую ChildView
.
Если скомбинировать эту опцию с filter, reorderOnSort
будет рендерить новые вложенные и удалять
те, что не прошли через filter
.
CollectionView’s emptyView
Когда коллекция не имеет детей, а вам нужно отобразить представление отличающиеся от обычного списка, вы можете определить аттрибут
emptyView
.
var NoChildrenView = Marionette.ItemView.extend({
template: "#show-no-children-message-template"
});
Marionette.CollectionView.extend({
// ...
emptyView: NoChildrenView
});
CollectionView’s getEmptyView
Если нужно emptyView
выбрать динамически, определите getEmptyView
:
Marionette.CollectionView.extend({
// ...
getEmptyView: function() {
// логика выбора "пустого" представления
return NoChildrenView;
}
});
CollectionView’s isEmpty
Если нужно контролировать, когда отображается пустое представление, определите isEmpty
:
Marionette.CollectionView.extend({
isEmpty: function(collection) {
// логика определения, что отображаемая коллекция "пустая"
return someBoolean;
}
});
CollectionView’s emptyViewOptions
Сходное с childView
и childViewOptions
, свойство emptyViewOptions
передастся в конструктор emptyView
.
Можно описать как литеральный объект или функцию.
Если emptyViewOptions
не определено в CollectionView, по умолчанию будет передаваться childViewOptions
в emptyView
.
var EmptyView = Marionette.ItemView({
initialize: function(options){
console.log(options.foo); // => "bar"
}
});
var CollectionView = Marionette.CollectionView({
emptyView: EmptyView,
emptyViewOptions: {
foo: "bar"
}
});
Callback методы
Есть несколько кэлюек методов определенных в CollectionView
. Если они определены, то будут вызываться базовыми методами
представления. Эти методы предназначены для использования внутри представления.
onBeforeRender callback
onBeforeRender
вызывается непосредственно перед рендерингом collection view
Marionette.CollectionView.extend({
onBeforeRender: function(){
// do stuff here
}
});
onRender callback
После рендеринга представления, вызовится метод onRender
. Можно определить этот метод, для связывания вашего кода
с отображенными элементами.
Marionette.CollectionView.extend({
onRender: function(){
// do stuff here
}
});
onBeforeReorder callback
Если reorderOnSort
установлен в true
, onBeforeReorder
будет вызван перед переупорядочиванием collectionView.
Marionette.CollectionView.extend({
onBeforeReorder: function(){
// do stuff here
}
});
onReorder callback
Если reorderOnSort
установлен в true
, после переупорядочивания collectionView будет вызван onReorder
.
Marionette.CollectionView.extend({
onReorder: function(){
// do stuff here
}
});
onBeforeDestroy callback
Этот метод вызывается перед удалением (разрушением) представления.
Marionette.CollectionView.extend({
onBeforeDestroy: function(){
// do stuff here
}
});
onDestroy callback
Этот метод вызывается после удаления (разрушения) представления.
Marionette.CollectionView.extend({
onDestroy: function(){
// do stuff here
}
});
onBeforeAddChild callback
Этот кэллбек позволит вам знать, когда добавляется вложенное представление в collectionView. Обеспечивает доступ к инстансу добавляемого представления. Вызвается непосредственно перед добавлением.
Marionette.CollectionView.extend({
onBeforeAddChild: function(childView){
// work with the childView instance, here
}
});
onAddChild callback
Этот кэллбек позволит вам знать, когда добавилось вложенное представленим в collectionView. Обеспечивает доступ к инстансу добавленного представления. Вызвается после добавления.
Marionette.CollectionView.extend({
onAddChild: function(childView){
// work with the childView instance, here
}
});
onBeforeRemoveChild callback
Этот кэллбек позволит вам знать, когда вложенное представление удаляется из collectionView. Обеспечивает доступ к инстансу удаляемого представления.
Marionette.CollectionView.extend({
onBeforeRemoveChild: function(childView){
// work with the childView instance, here
}
});
onRemoveChild callback
Этот кэллбек позволит вам знать, когда вложенное представление удалится (уже удалено) из collectionView. Обеспечивает доступ к инстансу удаленного представления.
Marionette.CollectionView.extend({
onRemoveChild: function(childView){
// work with the childView instance, here
}
});
CollectionView события
Есть несколько событий, что вызываются в течении жизненного цикла collectionView
. Каждое такое событие вызывается
функцией triggerMethod
(подробнее можно прочитать тут Marionette.triggerMethod )
и связано с соответсвующим on{EventName}
методом инстанса представления (дополнительная информмация above).
“before:render” событие
Вызывается непосредственно перед рендерингом представления.
Также триггерится, как collection:before:render
/ onCollectionBeforeRender
var MyView = Marionette.CollectionView.extend({...});
var myView = new MyView();
myView.on("before:render", function(){
alert("the collection view is about to be rendered");
});
myView.render();
“render” событие
Также будет вызываться событие “render:collection” / onRenderCollection
. Это позволит вам запускать больше чем один кэлбек
после рендеринга представления, и позволит родительскому представлению и другим частям приложения узнать, что представление
отрисовалось.
var MyView = Marionette.CollectionView.extend({...});
var myView = new MyView();
myView.on("render", function(){
alert("the collection view was rendered!");
});
myView.on("collection:rendered", function(){
alert("the collection view was rendered!");
});
myView.render();
“before:reorder” / “reorder” events
Когда reorderOnSort
установленно в true
, это событие будет вызываться перед/после реорганизацией коллекции.
var MyView = Marionette.CollectionView.extend({...});
var myCol = new Backbone.Collection({ comparator: ... })
var myView = new MyView({ reorderOnSort: true });
myView.render();
myCol.comparator = function () { return this.get('foo'); };
myView.on("before:reorder", function(){
alert("the collection view is about to be reordered");
});
myView.on("reorder", function(){
alert("the collection view has been reordered following its collection");
});
myCol.sort()
“before:destroy” event
Вызывается непосредствнно перед удалением представления, также вызываются “before:destroy:collection” /onBeforeDestroyCollection
var MyView = Marionette.CollectionView.extend({...});
var myView = new MyView();
myView.on("before:destroy:collection", function(){
alert("the collection view is about to be destroyed");
});
myView.destroy();
“destroy” / “destroy:collection” event
Вызывается сразу после удаления представления, вместе с вызовом соответсвующих методов.
var MyView = Marionette.CollectionView.extend({...});
var myView = new MyView();
myView.on("destroy:collection", function(){
alert("the collection view is now destroyed");
});
myView.destroy();
“before:add:child” / “add:child” event
“before:add:child” и соответвующий ему onBeforeAddChild
метод вызываются сразу после создания нового childView
инстанса
для “ребенка” добавленного в коллекцию, но прежде, чем представление будет отрендерено и добавлено в DOM.
“add:child” событие и соответсвующий ему onAddChild
метод триггерятся после того, как отрендеренное представление
добавляется в DOM
var MyCV = Marionette.CollectionView.extend({
// ...
onBeforeAddChild: function(){
// ...
},
onAddChild: function(){
// ...
}
});
var cv = new MyCV({...});
cv.on("before:add:child", function(viewInstance){
// ...
});
cv.on("add:child", function(viewInstance){
// ...
});
“before:remove:child”
Это событие триггерится после того, как childView инстанс удаляется из коллекции, но перед его разрушением.
cv.on("before:remove:child", function(childView){
// ...
});
“remove:child” event
Триггерится после удаления и разрушения вложенного (childView) представления из коллекции.
cv.on("remove:child", function(viewInstance){
// ...
});
“childview:*” всплытие событий от вложенных представлений
Когда вложенное представление вызывает событие, это событие будет всплывать к родителю с префиксом childview:
в имени события
Пэтому, если ребенок триггерит “do:something”, родительское представление стриггерит “childview:do:something”
// создаем простую коллекцию
var myModel = new MyModel();
var myCollection = new MyCollection();
myCollection.add(myModel);
var MyItemView = Marionette.ItemView.extend({
triggers: {
'click button': 'do:something' // отсылаем родителю событие `do:something` при клике
}
});
// get the collection view in place
var colView = new CollectionView({
collection: myCollection,
childView: MyItemView,
onChildviewDoSomething: function() {
alert("I said, 'do something!'");
}
});
colView.render();
В примере, когда кнопку, внутри вложенного предствления, нажмут, появится сообщение с текстом I said, ‘do something!’
Также можно присоединится к события вручную, используя обычный on
view.on('childview:do:something')
.
before:render:collection событие
before:render:collection
событие вызывается прежде чем дети collectionView
будут отрендерены и закешированны.
Отличается от collectionsView -> before:render
тем, что вызывается только, если collection
не пустая.
render:collection событие
render:collection
вызывается после того, как дети отрендерятся и закешируются.
Отличается от collectionsView -> render
тем, что вызывается только, если collection
не пустая.
CollectionView события от вложенных представлений
Следующие события всплывают от вложенных представлений в процессе своего жизненного цикла (происходящего в течении Region#show
)
before:render
/onBeforeRender
- Вызывается прежде, чем вложенное представление отрендерится.render
/onRender
- Вызывается после рендеринга представления, но до добавления его в DOMbefore:show
/onBeforeShow
- Вызывается после рендеринга представления, но перед его “включением” вcollectionView
представление.before:attach
/onBeforeAttach
- Вызывается перед добавлением в DOM. Не будет вызываться, еслиcollectionView
не присоединен в DOM.attach
/onAttach
- Вызывается после добавления в DOM. Не будет вызываться, еслиcollectionView
не присоединен в DOM.show
/onShow
- Вызывается когда представление отрендерено и “включено” вcollectionView
.dom:refresh
/onDomRefresh
- Вызывается когда представление отрендерено и показано, но только, если включено в DOM. Не будет вызываться, еслиcollectionView
не присоединен в DOM.before:destroy
/onBeforeDestroy
- Вызывается перед удалением представления.destroy
/onDestroy
- Вызывается после удаления представления.
Note: render
, destroy
, and dom:refresh
are triggered on pure Backbone Views during child view rendering,
but for a complete implementation of these events the Backbone View should fire render
within render()
and
destroy
within remove()
as well as set the following flags:
view.supportsRenderLifecycle = true;
view.supportsDestroyLifecycle = true;
CollectionView рендеринг
Метод render
отвечает за рендеринг всей коллекции. Проходит по каждой моделе в коллекции и рендерит его индивидуально,
как childView
.
var MyCollectionView = Marionette.CollectionView.extend({...});
// все вложенные представления будут отрендерены
new MyCollectionView().render();
CollectionView: Автоматический рендеринг
collection view
связывается с “add”, “remove” и “reset” событиями своей коллекции.
Когда коллекция сбрасывается ( “reset”), представление вызовет render
в себе и перерисует всю коллекцию.
При добавлении модели в коллекцию, будет сформированно представление этой модели и добавленно в коллекцию вложенным представлением.
Удаление модели из колллекции, вызовет уделние его из вложеного представления.
CollectionView: перерендеривание
Если вам нужно перерендерить всю коллекцию, вы можете вызвать view.render
метод. Этот метод позаботится об удалении
всех вложенных представлений.
CollectionView’s attachHtml
По умолчанию, CollectionView
, будет добавлять HTML каждого своего ребенка в буфер, затем вызовит jQuery.append
единожды
для добавления “буферного” HTML к родительскому el
.
Вы можете изменить это поведение, переопределив метод attachHtml
в определении вашего представления. Метод получает
три парметра и ничего не возращает.
Marionette.CollectionView.extend({
// The default implementation:
attachHtml: function(collectionView, childView, index){
if (collectionView.isBuffering) {
// buffering happens on reset events and initial renders
// in order to reduce the number of inserts into the
// document, which are expensive.
collectionView._bufferedChildren.splice(index, 0, childView);
}
else {
// If we've already rendered the main collection, append
// the new child into the correct order if we need to. Otherwise
// append to the end.
if (!collectionView._insertBefore(childView, index)){
collectionView._insertAfter(childView);
}
}
},
// Called after all children have been appended into the elBuffer
attachBuffer: function(collectionView, buffer) {
collectionView.$el.append(buffer);
},
// called on initialize and after attachBuffer is called
initRenderBuffer: function() {
this.elBuffer = document.createDocumentFragment();
}
});
Первый парметр инстанс CollectionView. что будет получать HTML из второго параметра, текущего childView инстанса.
Третий параметр, index
. Индекс модели в коллекции, что сейчас отрисовываем. Полезно для отсортированной колекции и
отображения сортированного списка в правильном порадке на экране.
Overrides of attachHtml
that don’t take into account the element
buffer will work fine, but won’t take advantage of the 60x performance
increase the buffer provides.
CollectionView’s resortView
По умолчанию CollectionView
будет отражать упорядочненость своей collection
в DOM. Но иногда представлению
требуется ререндеринг, что бы это было возможно. Например, если сменить компаратор (comparator
) у коллекции. По умолчанию,
CollectionView
будет вызывать метод render
когда это случится. Это может привести к большим издержкам. Вы можете
определить свою логику поведения, и отрисовывать только часть коллекции.
var cv = new Marionette.CollectionView({
collection: someCollection,
resortView: function() {
// тут логика ререндеринга после сортировки коллекции
}
});
CollectionView’s viewComparator
CollectionView позволяет определить опциюviewComparator
, если вы хотите отрисовывать вложенные представления в ином сортированном порядке,
отличном от сортировки в collection
var cv = new MarionetteCollectionView({
collection: someCollection,
viewComparator: 'otherFieldToSortOn'
});
viewComparator
может взять любой доступный Backbone.Collection
comparator formats
Например, sortBy
(функция принимающая один аргумент), или sort
(функция-компаратор, принимающая 2 аргумента),
или строку, указывающую на атрибут по которому идет сортировка.
CollectionView’s filter
Опция filter
позволяет не рендерить некоторые модели коллекции. Фильтр возращает истину, если ребенок будет отрисован, и
ложь, если не будет.
var cv = new Marionette.CollectionView({
childView: SomeChildView,
emptyView: SomeEmptyView,
collection: new Backbone.Collection([
{ value: 1 },
{ value: 2 },
{ value: 3 },
{ value: 4 }
]),
// Показываем только модели с четным числом
filter: function (child, index, collection) {
return child.get('value') % 2 === 0;
}
});
// рендерим представления с '2' и '4'
cv.render();
// изменяем фильтр
cv.filter = function (child, index, collection) {
return child.get('value') % 2 !== 0;
};
// рендерим представления с '1' и '3'
cv.render();
// удаляем фильтр
// обратите внимание. что использование `delete cv.filter` приведет к использованию `filter` определенному в прототипах,
// что может быть не уместно
cv.filter = null;
//рендерим все представления
cv.render();
CollectionView’s children
The CollectionView
использует Backbone.BabySitter для хранения и управления
своими вложенными представлениями. Это позволяет вам иметь легкий доступ к представлениям внутри CollectionView, итерировать их,
искать по индексу и т.д.
var cv = new Marionette.CollectionView({
collection: someCollection
});
cv.render();
// получаем представление по модели
var v = cv.children.findByModel(someModel);
// итерируем по всем вложенным представления и взаимодействем с каждой
cv.children.each(function(view){
// взаимодействем с представлением
});
Подробнее можно прочитать тут Backbone.BabySitter documentation.
CollectionView destroy
CollectionView
реализует метод destroy
, вызываемый менеджером регионов автоматически. Как часть реализации, будет
выполненно следующее:
- отвязывает все
listenTo
события - отвязывает все custom view события
- отвязывает все DOM события
- отвязывает все вложенные отренедренные представления
- удаляет
this.el
из DOM - вызывает
onDestroy
на представлении, если оно определено - возвращает
CollectionView
Обрабатвая onDestroy
событие, вы можете выполнить необходимый код после того, как представление уничтожится и
пройдет процесс очистки. Это дает возможность выполнить дополнительные процедуры очистки без лишнего переопределения метода destroy
Marionette.CollectionView.extend({
onDestroy: function() {
// custom cleanup or destroying code, here
}
});