【问题标题】:Backbone.Model: set collection as propertyBackbone.Model:将集合设置为属性
【发布时间】:2014-10-04 02:24:54
【问题描述】:

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

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) 删除 this.set 之前的 return ,更多信息 backbonejs.org/#changelog 阅读 1.1.0 部分。 2) model.isLoaded - 肯定不存在,这个属性应该标记为获取完成还是其他?
  • 您好,感谢您的评论。 1)我已经从initialize方法中删除了“return”(它是由coffeescript生成的),但它当然不能帮助我解决问题。 2) 你对我的理解是对的。我的意思是一些可以帮助我了解模型是否被获取的方法。
  • 能否附上代码如何加载单个模型,看起来我知道是什么原因。 2)如果您有兴趣,我可以提供基于同步事件的model.isLoaded实现

标签: backbone.js backbone-model


【解决方案1】:

“当我尝试加载单个模型时,我的属性被纯 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;
    });
}

【讨论】:

  • 感谢您的回复。现在,当我获取一个模型时它可以工作,但它不适用于集合。有点奇怪的是,当集合首先创建模型时,它调用“parse”方法,然后调用“initialize”方法。因此,当我通过集合获取模型时,我无法访问属性“标签”,因为它尚未初始化。