Backbone.Model:将集合设置为属性

时间:2014-08-11 09:39:37

标签: backbone.js backbone-model

我是骨干新手,面临以下问题。我试图模仿某种"有很多关系"。为实现这一点,我在模型中添加以下代码来初始化方法:

defaults: {
  name: '',
  tags: []
},
initialize: function() {
  var tags = new TagsCollection(this.get('tags'));
  tags.url = this.url() + "/tags";
  return this.set('tags', tags, {
    silent: true
  });
}

如果我通过集合获取模型,此代码非常有用。据我所知,第一个集合获取数据,然后此集合使用此数据填充模型。但是当我尝试加载单个模型时,我的属性被普通的Javascript数组覆盖。

m = new ExampleModel({id: 15})
m.fetch() // property tags get overridden after load

并回复:

{
  name: 'test',
  tags: [
     {name: 'tag1'}, 
     {name: 'tag2'}
  ]
}

任何人都知道如何解决这个问题?

还有一个问题。有没有办法检查模型是否加载。是的,我知道我们可以为fetch方法添加回调,但是像这个model.isLoaded或model.isPending呢?

谢谢!

1 个答案:

答案 0 :(得分:0)

  

“当我尝试加载单个模型时,我的属性被普通的Javascript数组覆盖”

您可以覆盖Model#parse方法以防止您的收藏被覆盖:

parse: function(attrs) {

    //reset the collection property with the new
    //tags you received from the server
    var collection = this.get('tags');
    collection.reset(attrs.tags);

    //replace the raw array with the collection
    attrs.tags = collection;

    return attrs;
}

  

“有没有办法检查是否加载了模型?”

您可以将模型与其默认值进行比较。如果模型处于默认状态(保存为id),则表示未加载。如果没有,则加载:

isLoaded: function() {

    var defaults = _.result(this, 'defaults');
    var current  = _.wíthout(this.toJSON(), 'id');

    //you need to convert the tags to an array so its is comparable
    //with the default array. This could also be done by overriding
    //Model#toJSON
    current.tags = current.tags.toJSON();

    return _.isEqual(current, defaults);
}

或者,您可以访问requestsyncerror事件,以跟踪模型同步状态:

initialize: function() {
    var self = this;

    //pending when a request is started
    this.on('request', function() {
        self.isPending = true;
        self.isLoaded = false;
    });

    //loaded when a request finishes
    this.on('sync', function() {
        self.isPending = false;
        self.isLoaded = true;
    });

    //neither pending nor loaded when a request errors
    this.on('error', function() {
        self.isPending = false;
        self.isLoaded = false;
    });
}