javascript - js是什麼 - backbone.js github



Backbone.js中的嵌套模型,如何處理 (8)

我有從服務器提供的以下JSON。 有了這個,我想創建一個嵌套模型的模型。 我不確定哪種方法可以實現這一點。

//json
[{
    name : "example",
    layout : {
        x : 100,
        y : 100,
    }
}]

我希望將這些轉換為兩個嵌套的主幹模型,其結構如下:

// structure
Image
    Layout
...

所以我像這樣定義了佈局模型:

var Layout = Backbone.Model.extend({});

但是,我應該使用以下兩種(如果有)技術中的哪一種來定義圖像模型? A或B以下?

一個

var Image = Backbone.Model.extend({
    initialize: function() {
        this.set({ 'layout' : new Layout(this.get('layout')) })
    }
});

或者, B

var Image = Backbone.Model.extend({
    initialize: function() {
        this.layout = new Layout( this.get('layout') );
    }
});

Answer #1

rycfung的美麗答案的CoffeeScript版本:

class ImageModel extends Backbone.Model
  model: {
      layout: LayoutModel
  }

  parse: (response) =>
    for propName,propModel of @model
      response[propName] = new propModel( response[propName], {parse:true, parentModel:this} )

    return response

這不甜嗎? ;)


Answer #2

使用主幹形式

它支持嵌套表單,模型和jSON。 全部嵌套

var Address = Backbone.Model.extend({
    schema: {
    street:  'Text'
    },

    defaults: {
    street: "Arteaga"
    }

});


var User = Backbone.Model.extend({
    schema: {
    title:      { type: 'Select', options: ['Mr', 'Mrs', 'Ms'] },
    name:       'Text',
    email:      { validators: ['required', 'email'] },
    birthday:   'Date',
    password:   'Password',
    address:    { type: 'NestedModel', model: Address },
    notes:      { type: 'List', itemType: 'Text' }
    },

    constructor: function(){
    Backbone.Model.apply(this, arguments);
    },

    defaults: {
    email: "[email protected]"
    }
});

var user = new User();

user.set({address: {street: "my other street"}});

console.log(user.toJSON()["address"]["street"])
//=> my other street

var form = new Backbone.Form({
    model: user
}).render();

$('body').append(form.el);

Answer #3

在編寫我的Backbone應用程序時,我遇到了同樣的問題。 必須處理嵌入/嵌套模型。 我做了一些調整,我認為這是一個相當優雅的解決方案。

是的,您可以修改解析方法來更改對象周圍的屬性,但所有這些實際上都是不可維護的代碼IMO,並且感覺比解決方案更像是黑客攻擊。

這是我為你的例子建議的:

首先像這樣定義你的佈局模型。

var layoutModel = Backbone.Model.extend({});

那麼這是你的圖片型號:

var imageModel = Backbone.Model.extend({

    model: {
        layout: layoutModel,
    },

    parse: function(response){
        for(var key in this.model)
        {
            var embeddedClass = this.model[key];
            var embeddedData = response[key];
            response[key] = new embeddedClass(embeddedData, {parse:true});
        }
        return response;
    }
});

請注意,我並沒有篡改模型本身,而只是從解析方法中傳回所需的對象。

這應該確保從服務器讀取時嵌套模型的結構。 現在,您會注意到保存或設置實際上並未在這里處理,因為我認為使用適當的模型明確設置嵌套模型是有意義的。

像這樣:

image.set({layout : new Layout({x: 100, y: 100})})

另外請注意,您實際上是通過調用以下方法在嵌套模型中調用解析方法:

new embeddedClass(embeddedData, {parse:true});

您可以根據需要在model字段中定義多個嵌套模型。

當然,如果您想盡可能將嵌套模型保存在自己的表格中。 這是不夠的。 但是在閱讀和保存整個對象的情況下,這種解決方案應該足夠了。


Answer #4

如果你不想添加另一個框架,你可以考慮創建一個帶有重寫settoJSON的基類並像這樣使用它:

// Declaration

window.app.viewer.Model.GallerySection = window.app.Model.BaseModel.extend({
  nestedTypes: {
    background: window.app.viewer.Model.Image,
    images: window.app.viewer.Collection.MediaCollection
  }
});

// Usage

var gallery = new window.app.viewer.Model.GallerySection({
    background: { url: 'http://example.com/example.jpg' },
    images: [
        { url: 'http://example.com/1.jpg' },
        { url: 'http://example.com/2.jpg' },
        { url: 'http://example.com/3.jpg' }
    ],
    title: 'Wow'
}); // (fetch will work equally well)

console.log(gallery.get('background')); // window.app.viewer.Model.Image
console.log(gallery.get('images')); // window.app.viewer.Collection.MediaCollection
console.log(gallery.get('title')); // plain string

你需要從這個答案中獲得BaseModel (可用,如果你喜歡, 作為要點 )。


Answer #5

我不確定Backbone本身有一個推薦的方法來做到這一點。 Layout對像在後端數據庫中是否有自己的ID和記錄? 如果是這樣,你可以像你一樣製作它自己的模型。 如果沒有,您可以將它保留為嵌套文檔,只需確保在saveparse方法中正確地將其轉換為JSON並將其轉換為JSON即可。 如果你最終採取了這樣的方法,我認為你的A示例與主幹更加一致,因為set會正確更新attributes ,但是我不確定Backbone默認使用嵌套模型做什麼。 很可能您需要一些自定義代碼來處理此問題。


Answer #6

我使用Backbone DeepModel插件來嵌套模型和屬性。

https://github.com/powmedia/backbone-deep-model

您可以綁定來更改事件的深度。 例如: model.on('change:example.nestedmodel.attribute', this.myFunction);


Answer #7

我將這段代碼作為Peter Lyon的建議重新定義解析的一個例子。 我有同樣的問題,這對我來說(與Rails後端)。 此代碼是用Coffeescript編寫的。 對於那些不熟悉它的人,我做了幾件事。

class AppName.Collections.PostsCollection extends Backbone.Collection
  model: AppName.Models.Post

  url: '/posts'

  ...

  # parse: redefined to allow for nested models
  parse: (response) ->  # function definition
     # convert each comment attribute into a CommentsCollection
    if _.isArray response
      _.each response, (obj) ->
        obj.comments = new AppName.Collections.CommentsCollection obj.comments
    else
      response.comments = new AppName.Collections.CommentsCollection response.comments

    return response

或者,在JS中

parse: function(response) {
  if (_.isArray(response)) {
    return _.each(response, function(obj) {
      return obj.comments = new AppName.Collections.CommentsCollection(obj.comments);
    });
  } else {
    response.comments = new AppName.Collections.CommentsCollection(response.comments);
  }
  return response;
};

Answer #8

我意識到我遲到了這個派對,但我們最近發布了一個插件來處理這種情況。 它被稱為backbone-nestify

所以你的嵌套模型保持不變:

var Layout = Backbone.Model.extend({...});

然後在定義包含模型時使用插件(使用Underscore.extend ):

var spec = {
    layout: Layout
};
var Image = Backbone.Model.extend(_.extend({
    // ...
}, nestify(spec));

之後,假設你有一個模型m ,它是Image一個實例,並且你已經從m上的問題中設置了JSON,你可以這樣做:

m.get("layout");    //returns the nested instance of Layout
m.get("layout|x");  //returns 100
m.set("layout|x", 50);
m.get("layout|x");  //returns 50




backbone-model