【问题标题】:Marionette multiple views inside a CollectionViewCollectionView 中的 Marionette 多个视图
【发布时间】:2013-11-25 00:39:00
【问题描述】:

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

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

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

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

  • 公寓集合视图(集合视图)
    • 公寓视图(复合视图)
      • 租户视图(ItemView)
      • 房间视图(复合视图)
        • 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 变得很棘手。

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

【问题讨论】:

    标签: backbone.js marionette backbone-views


    【解决方案1】:

    布局视图

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

    • 公寓集合视图(集合视图)
      • 公寓视图(布局视图)
        • 租户视图(ItemView)
        • 房间视图(CollectionView)
          • ChairView (ItemView)

    基本上,只要您的关卡需要多个同级视图(无论类型如何),都可以将它们一起包装在一个 LayoutView 中。

    LayoutView 事件

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

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

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

    你的设置会非常好,但这些都是开始的想法。

    不同的视图类型

    根据我的经验,这是不同类型的 Marionette 视图的细分:

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

    【讨论】:

      【解决方案2】:

      由于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/

      【讨论】:

      • 嗯,这就是我们的想法,Tenant 不仅仅是直接渲染。租户是一个复杂的对象,它将是它自己的视图并使用它自己的模型、事件、模板。将它放在一个独立的视图中会很好吗?
      • 它有一个错误:'Uncaught NoChildViewError: A "childView" must be specified '
      • 最近版本的 Marionette 将“itemView”更新为“childView”。这是修改后的小提琴:jsfiddle.net/re7x2vas。我建议看看我使用上面的 LayoutViews 得出的答案:stackoverflow.com/a/27449613/417822
      猜你喜欢
      • 1970-01-01
      • 2013-03-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-12
      • 1970-01-01
      相关资源
      最近更新 更多