Несколько нюансов работы с backbone, вызывающих затруднения у новичков.
Обычно атрибуты модели имеют простые типы (строка или число). Но иногда необходимо, что бы атрибут был моделью или коллекцией. Например, атрибут «frends» в данной модели должен быть коллекцией:
Но если вы сфетчите данные, то атрибут «frends» будет просто объектом. Для того, что бы преобразовать его в коллекцию, переопределяем метод «set»:
Следующая проблема, которая возникает при использовании «сложных атрибутов» — это преобразование таких объектов в json. Для этого переопределяем функцию toJSON у объекта, содержащего такой атрибут:
У модели коллекции есть атрибут 'obj_type'. Для того, чтобы быстро изменить этот атрибут во всех объектах:
Предположим, у нас во вьюхе обрабатывается resize всего окна. Разумеется, при удалении объекта нужно отписаться от события:
К сожалению, роутер на странице может быть один. Но можно костыльнуть и вызывать дополнительный роутер из основного. Для этого:
И само подключение:
Атрибут является коллекцией или моделью
Обычно атрибуты модели имеют простые типы (строка или число). Но иногда необходимо, что бы атрибут был моделью или коллекцией. Например, атрибут «frends» в данной модели должен быть коллекцией:
appTest.Models.modelMan = Backbone.Model.extend({
'default':{
...
frends:{}
}
})
Но если вы сфетчите данные, то атрибут «frends» будет просто объектом. Для того, что бы преобразовать его в коллекцию, переопределяем метод «set»:
set: function(attributes, options){
if(!(attributes.frends instanceof appTest.Collections.listMan)) {
attributes.frends = new appTest.Collections.listMan (attributes.frends);
}
return Backbone.Model.prototype.set.call(this, attributes, options);
},
Преобразование модели, содержащей «сложный» атрибут в JSON
Следующая проблема, которая возникает при использовании «сложных атрибутов» — это преобразование таких объектов в json. Для этого переопределяем функцию toJSON у объекта, содержащего такой атрибут:
toJSON: function(){
var json = _.clone(this.attributes);
for(var attr in json) {
if((json[attr] instanceof Backbone.Model) || (json[attr] instanceof Backbone.Collection)) {
json[attr] = json[attr].toJSON();
}
}
return json;
}
Для всех записей коллекции устанавливаем одно значение
У модели коллекции есть атрибут 'obj_type'. Для того, чтобы быстро изменить этот атрибут во всех объектах:
setObjType: function(idObjType){
this.invoke('set',{'obj_type':idObjType})
},
Действие при удаление объекта
Предположим, у нас во вьюхе обрабатывается resize всего окна. Разумеется, при удалении объекта нужно отписаться от события:
appTest.Views.Main = Backbone.View.extend({
initialize: function(){
$(window).on('resize', _.bind(this.eventWindowResize, this));
}
remove: function() {
$(window).off("resize", this.eventWindowResize);
Backbone.View.prototype.remove.apply(this, arguments);
},
})
Несколько роутеров на одной странице
К сожалению, роутер на странице может быть один. Но можно костыльнуть и вызывать дополнительный роутер из основного. Для этого:
- В основном роутере создаем список внешних роутеров (extraRouter);
- В основном роутере пишем функцию (addRouter), который будет заносить в список внешних роутеров и регистрировать новые правила из этого роутера на наш основной роутер.
appMainPage.Controller.main = Backbone.Router.extend({
extraRouter: {},
/**
* Добавить внешний роутер<br>
* Все события, которые нет у нас будут прописан на аналогичную функцию с префиксом
* @param rout Роутер
* @param prefix Под какти именем фигурирует
*/
addRouter: function(rout, prefix){
this.extraRouter[prefix] = rout;
for(var rules in rout.routes) {
var name = rout.routes[rules];
if(this[name] == undefined){
var nameFun = prefix + '_' + name;
if(this[nameFun] == 'undefined')
console.log('Нет метода ' + nameFun);
else
this.route(rules, nameFun);
}
}
},
/**
* Показать новость
* Вызывается из внешнего роутера
* @param idnews
*/
news_show_news: function(idnews){
this.renderMainPage();
var router = this.extraRouter['news'];
router.show_news(idnews);
},
})
И само подключение:
appNews.route = new appNews.Controller.main;
appMainPage.route = new appMainPage.Controller.main;
appMainPage.route.addRouter(appNews.route, 'news');
if(!Backbone.History.started)
Backbone.history.start();