我有两个在Backbone模型上调用fetch的函数。第一个使用id创建模型的新实例并调用fetch(),第二个使用id从集合中检索现有模型实例并调用fetch()。在第一个中,模型的解析功能被触发,但不在第二个...但我不知道为什么。
第一个(触发解析)
App.fetchItemFromCollectionById = function (id) {
App.myItem = App.myItemCollection.get(id);
App.myItem.fetch({
traditional: true,
data: {
elements: 'all',
format:'json',
},
success: function(){
App.myItemView = new App.ItemView({
el: $('#active-item'),
model: App.myItem,
});
App.myItemView.render();
}
});
};
第二个(不会触发解析)
App.Item = Backbone.Model.extend({
urlRoot: '/api/v1/item/',
defaults: {
},
initialize: function(){
},
parse : function(response){
console.log('parsing');
if (response.stat) {
if (response.content.subitems) {
this.set(‘subitems’, new App.SubitemList(response.content.subitems, {parse:true}));
delete response.content.subitems;
this
}
return response.content;
} else {
return response;
}
},
});
我读过的所有文档都说,模型的解析函数总是在获取时被调用。
任何人都知道为什么在第二个问题上没有触发解析?
这是模型定义:
App.ItemList = Backbone.Collection.extend({
url: '/api/v1/item/',
parse : function(response){
if (response.stat) {
return _.map(response.content, function(model, id) {
model.id = id;
return model;
});
}
}
});
固定,感谢EMILE& COREY - 以下解决方案
事实证明,当我第一次加载App.MyItemCollection时,集合中的模型只是通用模型,没有正确地转换为App.Item的实例。添加"模型:App.Item"收集定义解决了问题。见下文:
ORIGINAL
App.ItemList = Backbone.Collection.extend({
url: '/api/v1/item/',
model: App.Item,
parse : function(response){
if (response.stat) {
return _.map(response.content, function(model, id) {
model.id = id;
return model;
});
}
}
});
更新,已解决的问题
createMovie(movie: Movie): void {
this._dataService.createMovie<Movie>({'name': 'Star Wars'})
.subscribe((data) => this.movies.push(data),
error => () => {
'something went wrong';
},
() => {
// console.log(this.movies);
});
}
答案 0 :(得分:2)
parse
时调用fetch
在Backbone source中,我们可以看到仅在parse
异步请求成功时调用fetch
函数。
fetch: function(options) {
options = _.extend({parse: true}, options);
var model = this;
var success = options.success;
// The success callback is replaced with this one.
options.success = function(resp) {
// parse is called only if the fetch succeeded
var serverAttrs = options.parse ? model.parse(resp, options) : resp;
// ...snip...
// then the provided callback, if any, is called
if (success) success.call(options.context, model, resp, options);
};
wrapError(this, options);
return this.sync('read', this, options);
},
只要服务器返回模型的数据,就会调用parse ,
fetch
和save
。
假设fetch
失败,服务器不会返回任何模型数据,因此不会调用解析。
要使fetch
成功使用现有模型,默认行为要求模型在其id
哈希中具有attributes
。
cid
仅用于在本地区分模型,并且不会自行进行提取。
模特的特殊属性, cid 或客户ID 是唯一的 标识符在首次显示时自动分配给所有模型 创建。当模型尚未保存到时,客户端ID很方便 服务器,并且还没有最终的真实ID 需要在用户界面中显示。
作为mentioned by Cory Danielson,如果myItemCollection
集合中未设置model
property,则会调用默认模型parse
,而不是App.Item
模型&# 39; s parse
。
您不应该在parse
函数中实例化模型,因为它是集合的责任。
App.ItemList = Backbone.Collection.extend({
model: App.Item, // make sure to set this property
url: '/api/v1/item/',
parse : function(response){
if (response.stat) {
return _.map(response.content, function(model, id) {
model.id = id;
return model;
});
}
}
});
如果您未在集合上设置model
property,那么只要您在集合中使用add
或set
,您就会面对同样的问题,您的新模型将是Backbone.Model
个实例,而不是App.Item
个实例。
parse
您的parse
函数有一些您应该了解的代码味道:
parse
不应该对模型产生任何副作用。它应该接收数据并返回转换后的数据。undefined
。delete
效率不高,只返回一个新对象会更好。无论如何,这是你应该避免的另一个副作用。话虽这么说,我看到你在解析中将一个集合嵌套在模型的attributes
哈希中。我会建议反对这种模式有几个原因:
parse: true
,并且永远不要在模型外设置subitems
。default
现在更加复杂,因为您必须记住属性中有一个集合。我已经在以下答案中列出了多种解决方案:
答案 1 :(得分:0)
您的收藏品可能不会使用相同的模型类别来处理它的模型属性。这就是解析该特定模型的原因。
如果model
属性未设置为您期望的模型,则不会在该模型上调用解析。默认情况下,该集合将使用Backbone.Model。
MyItemCollection = Backbone.Collection.extend({
model: App.Item
});
你可能拥有的是这样的东西
MyItemCollection = Backbone.Collection.extend({
model: Backbone.Model.extend({
urlRoot: '/api/v1/item/'
})
});