簡體   English   中英

主干模型 fetch() 不調用解析

[英]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文檔說:

每當服務器在fetchsave返回模型的數據時,就會調用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上使用addset ,我們都會面臨同樣的問題,我們的新模型將是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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM