[英]Backbone model fetch() not calling parse
我有两个函数在 Backbone 模型上调用 fetch。 第一个使用 id 创建模型的新实例并调用 fetch(),第二个使用 id 从集合中检索现有模型实例并调用 fetch()。 在第一个中,模型的解析函数被触发,但在第二个中没有......我不知道为什么。
第一个(触发解析)
App.fetchItemById = function (id) {
App.myItem = new App.Item({id: 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.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;
}
},
});
已修复,感谢 EMILE & Corey - 解决方案如下
原来,当我第一次加载 App.MyItemCollection 时,集合中的模型只是通用模型,没有正确转换为 App.Item 的实例。 在集合定义中添加“model: App.Item”解决了这个问题。 见下文:
原版
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;
});
}
}
});
更新,已解决的问题
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;
});
}
}
});
fetch
调用parse
在Backbone 源码中,我们可以看到parse
函数只有在fetch
async 请求成功时才会被调用。
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
返回模型的数据时,就会调用parse 。
假设fetch
失败,服务器不会返回任何模型数据,因此不会调用 parse。
为了对现有模型进行成功fetch
,默认行为要求模型在其attributes
哈希中具有一个id
。
cid
仅用于在本地区分模型,不能单独用于获取。
模型的一个特殊属性, cid或客户端 id是一个唯一标识符,它在首次创建时自动分配给所有模型。 当模型尚未保存到服务器时,客户端 id 很方便,并且还没有最终的真实 id,但已经需要在 UI 中可见。
正如Cory Danielson所提到的,如果model
属性未在myItemCollection
集合上设置,则将myItemCollection
默认模型parse
,而不是您的App.Item
模型的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
属性,那么无论何时我们在set
上使用add
或set
,我们都会面临同样的问题,我们的新模型将是Backbone.Model
实例而不是App.Item
实例。
parse
的副作用你的parse
函数有一些你应该知道的代码味道:
parse
不应该对模型产生任何副作用。 它应该接收数据并返回转换后的数据,就是这样。undefined
。delete
效率低下,最好只返回一个新对象。 无论如何,这是您应该避免的另一个副作用。话虽如此,我看到您在解析中的模型的attributes
哈希中嵌套了一个集合。 出于以下几个原因,我建议不要采用这种模式:
parse: true
,并且永远不要在模型之外设置subitems
。default
值现在更加复杂,因为您必须记住属性中有一个集合。我已经在这里回答了这些问题有多种解决方案:
您的集合可能没有为其模型属性使用相同的模型类。 这就是为什么不会调用对该特定模型的解析。
如果model
属性未设置为您期望的模型,则不会对该模型调用 parse。 默认情况下,集合将使用 Backbone.Model。
MyItemCollection = Backbone.Collection.extend({
model: App.Item
});
你可能拥有的是这样的
MyItemCollection = Backbone.Collection.extend({
model: Backbone.Model.extend({
urlRoot: '/api/v1/item/'
})
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.