【问题标题】:Backbone collections representing tree data表示树数据的主干集合
【发布时间】:2011-05-17 05:49:58
【问题描述】:

我想以树的形式将 json 数据加载到 Backbone 集合中。我不能这样做。谁能解释我做错了什么?

我的非常简单的模型:

CTreeDataItem = Backbone.Model.extend(
{
});
CTreeDataItems = Backbone.Collection.extend(
{
    model: CTreeDataItem
});

还有我的加载尝试:

    var treeJs =
        [
            { id: "tvRoot", title: 'Root', cssClass: 'root',
                items: [
                    { id: "ti1", title: 'Item1', cssClass: 'item',
                        items: [
                            { id: "ti11", title: 'SubItem11', cssClass: 'subitem'},
                            { id: "ti12", title: 'SubItem12', cssClass: 'subitem'}]},
                    { id: "ti2", title: 'Item2', cssClass: 'item',},
                    { id: "ti3", title: 'Item3', cssClass: 'item', 
                        items: [
                            { id: "ti31", title: 'SubItem31', cssClass: 'subitem'},
                            { id: "ti32", title: 'SubItem32', cssClass: 'subitem'},
                            { id: "ti33", title: 'SubItem33', cssClass: 'subitem'}]}]
        }];
    this.TreeData = new CTreeDataItems();
    this.TreeData.add(treeJs);

【问题讨论】:

  • 您期望的最终结果是什么,它在哪里失败了?您是否希望将每个节点表示为一个模型,并在其上包含一组子节点?
  • "您是否希望将每个节点表示为一个模型,并在其上包含一组子节点?" - 这正是我所期望的。失败是加载模型只有根元素已被嵌套。所以我有collection(1el)/model(root)/collection(1el)/model(root)/至少4个-5lvls。我不知道它有多深以及为什么它不会触发异常
  • 好的,有道理。我正在尝试提出一个如何做到这一点的示例,一旦我克服了一个不会消失的异常,我就会发布它。

标签: javascript backbone.js


【解决方案1】:

尝试用Model作为节点来表示树,每个节点都包含一个Collection的子节点:

var CTreeDataItem = Backbone.Model.extend({
    initialize: function() {
        if (Array.isArray(this.get('items'))) {
            this.set({items: new CTreeDataItemChildren(this.get('items'))});
        }
    }
});

// children collection
var CTreeDataItemChildren = Backbone.Collection.extend({
    model: CTreeDataItem
});

// create
var treeData = new CTreeDataItemChildren(treeJs);

// access
treeData.at(0).get('items').at(1).get('title')
// returns "Item2"

编辑 2011-05-18:如果您想展平树并维护对树中每个节点的父节点的引用:

// flatten the tree outside of Backbone. Alternatively,
// you could override the constructor of the CTree collection
// to provide encapsulation
function flatten(parentID, arr) {
    var out = [];
    for (var i = 0; i < arr.length; i++) {
        var node = arr[i];
        node.parentID = parentID;
        out.push(node);
        if (Array.isArray(node.items))
            Array.prototype.push.apply(out, flatten(node.id, node.items));
        delete node.items;
    }
    return out;
}

// remove above code that would have provided nesting
var CTreeDataItem = Backbone.Model.extend({});

// children collection, as before 
var CTreeDataItemCollection = Backbone.Collection.extend({
    model: CTreeDataItem
});

// create
var treeData = new CTreeDataItemChildren(flatten('', treeJs));

// as before, but now there's the 'parentID' FK
treeData.at(3).get('parentID')
// returns "ti1"

希望这就是你所追求的。

【讨论】:

  • 嗯,有不同的方法可以展平树状结构。我宁愿选择项目具有 parentId 的关系数据库格式。或者我可以对项目进行排序并保留它们的缩进。我只是好奇为什么我不能以 json 格式加载树数据,从同一类型创建嵌套集合和模型。
  • 上面的代码确实将树数据加载到包含嵌套模型集合的模型集合中,所以......不确定我是否遵循。因此,您要寻找的是展平树,将子节点放在与其父节点相同的轴上,并使用一些“外键”引用它在前树结构中的父节点?
  • 事实上我选择了第三种解决方案。以列表格式重新组织我的后端数据。这实际上是你的函数 flatten 所做的,但不需要它:)
【解决方案2】:

您需要使用Backbone.Model parse 方法,该方法用于在将数据传递给模型之前对其进行解析。您可以使用它将树的每个级别上的数据转换为代表这些集合中项目的集合和模型。

然后,在保存时,您必须覆盖模型上的 toJSON 方法,以便以与接收数据相同的方式返回数据的 json 表示。 Backbone.sync 稍后使用它将数据发送回服务器。默认情况下,它只返回您的Model.attributes 中的_.clone,并且您还希望其中的所有集合和集合模型。

所有人都为骨干欢呼! :)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-05-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-20
    相关资源
    最近更新 更多