在Backbone中设置父属性的正确方法是什么?

时间:2012-06-18 21:39:11

标签: backbone.js

我有一个JSON文件,可以创建我的ParentModel以及填充子Records集合。

ParentModel : Backbone.Model.extend({
  initialize: function() {
    this.set({ records: new Records(this.get("records")) });
  }
});

Record集合只是一个映射到Record模型的基本Backbone集合。

问题是我需要孩子知道父母,所以每个Record模型必须有一个父属性。所以现在我只是将它添加到initialize方法的底部:

var self = this;
this.get("records").each(function(record) {
  record.set("parent", self);
});

这很好用,但是当我创建一个新记录时,我宁愿不记得包含这4行。

This answer说我可以覆盖初始化方法以获取其他参数,但我不太确定如何让Backbone自动将ParentModel传递给重写的initialize方法。任何人都可以提供一个如何做到这一点的例子吗?

我听说Backbone-relational可能有助于做我想要的事情,但这又是另外23kb要包括的内容。如果这是更好的方法,我会考虑实施它,但除此之外我更喜欢一个更简单的解决方案。

无论是通过代码创建新的ParentModel记录,还是通过JSON Feed自动创建,都需要这样做。

2 个答案:

答案 0 :(得分:4)

我通常发现从结构元素中移出属性更清晰,因此我的记录和父属性都在对象上,而不是属性。也就是说,您可以利用集合和父对象上的不同事件:

var ParentModel = Backbone.Model.extend({
    initialize: function () {
        _.bindAll(this, 'adoptOne', 'adoptAll');
        this.records = new Records();

        this.on('change:records', function () {
             this.records.reset(this.get('records'));
        });
        this.records.on('reset', this.adoptAll);
        this.records.on('add', this.adoptOne);

        this.records.reset(this.get('records'));
    },

    adoptAll: function () {
       this.records.each(this.adoptOne);
    },
    adoptOne: function (model) {
        model.parent = this;
    }
});

一些测试:

var p = new ParentModel({
    name: "I am the parent",
    records: [{id: 1}, {id: 2}]
});

p.records.add({id: 3});

p.records.each(function (child) {
    console.log(child.get('id')+' '+child.parent.get('name'));
});

p.set({records: [{id: 4}]});

p.records.each(function (child) {
    console.log(child.get('id')+' '+child.parent.get('name'));
});

小提琴http://jsfiddle.net/sPXaZ/

答案 1 :(得分:1)

为了清楚起见,以下是您的一个需求摘要(可以在问题评论中找到):

  

例如,如果我想将Record元素置于中心位置,我需要   知道视图框的宽度。知道这一点的唯一方法就是知道   什么是最广泛的记录元素。父对象可以告诉我   通过对子元素进行排序。

在我看来,你的模型必须处理显示问题; Backbone中的显示由Views处理。所以,我猜你可以创建一个同时收听ParentModelRecords的视图。

var RecordView = Backbone.View.extend({
  initialize: function() {
    this.collection.on('sync', this.render, this);
  }
  render: function() {
    var widest = this.model.get('width');
  }
});

var view = new RecordView({model: ParentModel, collection: Records});

而且,在我看来,这不是ParentModel来处理它在屏幕上占据的宽度,而是它自己的View。在这里引入两个观点似乎是重点。

但是我还没有完整的图片,所以,如果我错了,请给我更多你想要做的样本。