Marionette在CollectionView中有多个视图

时间:2013-11-25 00:39:01

标签: backbone.js marionette backbone-views

我一直在阅读和研究,但我无法弄清楚如何为Backbone / Marionette项目组织嵌套的复杂视图。 Two Collections inside a Composite View中的答案与我认为需要的答案非常接近,但在处理其中一个集合项目中的多个视图时似乎不尽如人意。

我将通过在该问题中扩展公寓示例answer来解释。

假设我们有一系列公寓,一系列房间,列出了他们的椅子。另外,让我们加入公寓租户。作为租户视图的想法可以拥有自己的视图管理,事件,并在网站的其他地方重复使用。

根据我的理解,它可能看起来像:

  • ApartmentCollectionView(CollectionView)
    • ApartmentView(CompositeView)
      • TenantView(ItemView)
      • RoomView(CompositeView)
        • ChairView(ItemView)

我的问题是ApartmentView不允许多个子视图。

@ scott-puleo提供的答案副本,加上租户。

var apartments = [
    {apartment: '1a',
        rooms: [
            {name: 'master bed', chairs: []},
            {name: 'kitchen', chairs: [
                {chairType: 'stool'}, {chairType: 'stool'}]},
            {name: 'living room', chairs: [
                {chairType: 'sofa'}, {chairType: 'love seat'}]}],
        tenant:{name:Bob Jones,phone:6165551234}
    },
    {apartment: '2a', 
        rooms: [
            {name: 'master bed', chairs: []},
            {name: 'kitchen', chairs: [
                {chairType: 'shaker'}, {chairType: 'shaker'}]},
            {name: 'living room', chairs: [
                {chairType: 'sectional'}]}]
        tenant:{name:Hope Smith,phone:6365551234}
    }];

var chairModel = Backbone.Model.extend({});

var roomModel = Backbone.Model.extend({
    initialize: function(attributes, options) {
        this.chairs = new Array();
        _.each(attributes.chairs, function(chair){
          this.chairs.push(new chairModel(chair));    
        }, this);
    }          
});

var ApartmentModel = Backbone.Model.extend({
    initialize: function(attributes, options) {
        this.rooms = new Array();
        _.each(attributes.rooms, function(room){
          this.rooms.push(new roomModel(room));    
        }, this);
    }  
}); 

var ApartmentCollection = Backbone.Collection.extend({
    model: ApartmentModel
});

var ChairView = Backbone.Marionette.ItemView.extend({
    template:'#chair'
});

var TenantView = Backbone.Marionette.ItemView.extend({
    template:'#tenant'
});

var RoomView = Backbone.Marionette.CompositeView.extend({
    template: '#room',
    itemViewContainer: 'ul',
    itemView: ChairView,
    initialize: function(){
        var chairs = this.model.get('chairs');
        this.collection = new Backbone.Collection(chairs);
    }
});   

var ApartmentView = Backbone.Marionette.CompositeView.extend({
    template: '#appartment',
    itemViewContainer: 'ul',
    itemView: RoomView,      // Composite View
    initialize: function(){
        var rooms = this.model.get('rooms');
        this.collection = new Backbone.Collection(rooms);
    }
});   

var ApartmentCollectionView = Backbone.Marionette.CollectionView.extend({
    itemView: ApartmentView  // Composite View
});

apartmentCollection = new ApartmentCollection(apartments);

apartmentCollectionView = new ApartmentCollectionView({
    collection: apartmentCollection
});    

App.apartments.show(apartmentCollectionView);

我觉得我应该考虑为每个公寓发起个人LayoutsControllers,但是效率不高,我认为这也不是他们想要的。这些也可能使管理区域中的ID变得棘手。

感谢您的任何指示,我会更新我可能发现的任何答案。

2 个答案:

答案 0 :(得分:1)

LayoutViews

我找到的答案是使用LayoutViews,在此示例中用于AppartmentView。 LayoutViews扩展了ItemView,因此也使用了模型。但是,它们还支持多个区域,然后可以包含任何类型的视图(ItemView,CollectionView,CompositeView,LayoutView)。

  • ApartmentCollectionView(CollectionView)
    • ApartmentView(LayoutView)
      • TenantView(ItemView)
      • RoomsView(CollectionView)
        • ChairView(ItemView)

基本上,只要你的某个级别需要多个兄弟级别的视图(不论其类型),它们就可以在LayoutView中包装在一起。

LayoutView事件

关于视图之间的事件和通信的快速说明,因为这很快就会变得有趣。 Marionette相信自上而下的事件倾听。那是父母可以听孩子,但孩子应该能够独立跑,而不需要听父母。

所以,当一个事件发生在兄弟姐妹需要做出反应的视图中时 - 它应该是父母应该监听孩子的事件..然后触发或调用另一个孩子需要的功能反应。

或者,可以设置父级别的模型,然后子级可以设置值,其他视图可以监听更改事件。

您的设置会很好,但这些都是您的想法。

不同的视图类型

根据我的经验,这是不同类型的木偶观点的细分:

  • ItemView→(1型号)
  • CollectionView→(1 Model,1 Collection)
  • CompositeView→(1个模型,1个集合,1个区域,1个子视图[该区域的任何类型])
  • LayoutView→(1个模型,1个RegionManager [∴任意数量的子视图,任何类型])

答案 1 :(得分:0)

由于Tenant不是单独的骨干模型,而是Apartment的一部分,它被序列化并传递给ApartmentView,因此可以直接呈现。

只有在此模式下才需要进行更改:

<script type="text/html" id="apartment">
    <div>
        <h2>Apartment: <%=apartment%></h2>
        <ul></ul>
        <b><%= tenant.name %>, <%= tenant.phone %></b>
    </div>
</script>

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