[英]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.