Backbone:为视图分配不同的集合

时间:2013-04-29 13:40:11

标签: backbone.js marionette backbone-views backbone-collections

在Backbone(实际上是Marionette)中初始化视图后,是否可以更改其集合?我使用一个(主要)项目列表的嵌套模型和其他子项目。视图显示所有主要项目,并且根据这些项目的当前选择,子项目视图会更改。我看到的唯一选项是在选择更改后使用所选主项的子项重新创建子项视图。

以下是模型:

model = [
  {
    foo: 'blah',
    bar: [{a: 1, b: 2, c: '3'}, {a: 4, b: 5, c: null}]
  },
  {
    foo: 'abcd',
    bar: [{a: 6, b: 7, c: '8'}, {a: 9, b: 10, c: '11'}]
  }
]

该视图有两个并排的表:

Table1      Table2
------      ------
 blah        a=6, b=7, c='8'
*abcd        a=9, b=10, c='11'

*表示当前选定的主要项目。我可以在选择时检索table1中所选主项的索引,但是如何重新初始化table2中的视图?

编辑: 以下是一些进一步说明的代码:

var MainCollectionViewRow = Backbone.Marionette.ItemView.extend({
    template: _.template(...),
    tagName: 'tr'
});

var MainCollectionView = Backbone.Marionette.CompositeView.extend({
    tagName: 'table',
    template: _.template(...),
    itemView: MainCollectionViewRow,
    events: {
        'click tbody tr': 'selectItem',
    },
    appendHtml: function(collectionView, itemView, index) {
        $(itemView.el).data('index', index);
        collectionView.$('tbody').append(itemView.el);
    },
    selectItem: function(e) {
        var index = $(e.currentTarget).data('index');
        var newMainItem = this.collection.at(index);
        // This doesn't work...
        subView.initialize({'collection': newMainItem.get('bar')});
    }
});

var Bar = Backbone.Model.extend({
    defaults: {
        a: null,
        b: 0,
        c: 'text',
    }
});

var BarCollection = Backbone.Collection.extend({
    model: Bar
});

var Main = Backbone.Model.extend({ 
    defaults: {
        foo: null, 
        bar: BarCollection,
    },
    initialize: function() {
        var bar = new BarCollection(this.get('bar'));
        this.set('bar', bar);
    }
});

var MainCollection = Backbone.Collection.extend({
    model: Main,
    url: '/some/url/'
});

app.someRoute = function() {
    var region = new MainRegion();
    var layout = new MainLayout();
    region.show(layout);

    new MainCollection().fetch({
        success:function (list) {
            mainView = new MainCollectionView({
                collection: list
            });
            var subItem = list.first();
            subView = new SubCollectionView({
                collection: list.get('bar')
            });

            layout.main.show(mainView);
            layout.sub.show(subView);
        }
    });
}

app.route('some/route', 'someRoute');

1 个答案:

答案 0 :(得分:1)

我建议使用Marionette的控制器。这是一个更多的代码,但随着您的应用程序的增长,您将能够保持您的集合和查看逻辑清洁。您还将获得可书签链接以及后退和前进浏览器操作的使用。

var Router = Marionette.AppRouter.extend({
    appRoutes: {
        "": "navigate",
        "section/:index": "navigate"
    },
});

var Controller = Marionette.Controller.extend({

    initialize: function(options){
        this.region = new MainRegion();
        this.layout = new MainLayout();

        this.mainCollection = new MainCollection();
        this.subCollection = new Backbone.Collection();

        this.mainView = new MainCollectionView({
            collection: this.mainCollection
        });
        this.subView = new SubCollectionView({
            collection: this.subCollection
        });
    },
    navigate: function(index){
        index = index || 1;
        var subList = this.mainCollection.at(index);
        this.subView.collection.reset(subList);
    },
    start: function(){
        var self = this;
        var p = this.mainCollection.fetch();

        p.done(function(){
            self.showRegion();
            self.showLayout();
        })
    },
    showRegion: function() {
        this.region.show(this.layout);
    },
    showLayout: function() {
        this.layout.main.show(this.mainView);
        this.layout.sub.show(this.subView);
    }

});

Mod.addInitializer(function(){
    Mod.controller = new Controller();
    Mod.router = new Router({
        controller: Mod.controller
    });
    Mod.controller.start();
});

MainCollectionView:我们现在可以依靠路由来处理这个问题,更新你的视图以使用链接。

//selectItem: function(e) {
  //var index = $(e.currentTarget).data('index');
  //var newMainItem = this.collection.at(index);
  // reset the collection http://backbonejs.org/#Collection-reset
  //subView.collection.reset(newMainItem.get('bar'));
//}

SubCollectionView:

initialize: function() {
  _.bindAll(this);
  this.collection.on("reset", this.render, this);
}