CollectionView - collection 数据未传递给 childView

CollectionView - collection data not being passed to childView

我正在尝试让 collectionView 工作,但我不太确定 CollectionView 是否自动启动 fetch 方法然后填充 ChildViews与获取的数据。或者这是我需要手动做的事情吗?我查看了 Marionette 文档页面,但找不到任何合适的示例来回答我的问题。

下面的例子是我到目前为止得到的,collection 填满了所有需要的数据,但由于某种原因数据没有传递给子视图。

每当我调用'http://localhost/GetCategories'时返回下面的JSON:

JSON数据:

[{"category_id":"Category1","category_name":"Category One"}, 
 {"category_id":"Category2","category_name":"Category Two"}]

collection:

  define([ 'underscore',  'backbone',  'models/MainMenu/MM.model.category'], function(_, Backbone, m_Category){
      var CategoriesCollection = Backbone.Collection.extend({
        model: m_Category,

        url : 'GetCategories';

        initialize: function() {
            console.log('CategoriesCollection initialized...');
            this.fetch()
        }

      });


  return CategoriesCollection;
});

collection查看:

define([ 'backbone', 'underscore', 'marionette', 
    'collections/MainMenu/collection.categories' , 
    'layouts/MainMenu/itemview.category'], 
    function (Backbone, _, Marionette, c_Categories, iv_Category) {
    "use strict";
    var CategoriesCollectionView = Marionette.CollectionView.extend({

        tagName: 'div',

        template: null,

        id: 'categories',

        childView: iv_Category,

        collection : new c_Categories(),

        initialize: function(){
            console.log('Categories Collection: initialized');

            /// or should I call fetch() from within the CV? 
            /// but how do I then pass all the data to ChildView? 
            this.collection.fetch().done(function(){

            })
        },
        onRender: function(){
            console.log(this.collection) ///<-- shows all the JSON data properly
        },
        onShow: function(){
        }
    });

    return CategoriesCollectionView;
});

项目视图:

define([ 'backbone', 'underscore', 'marionette', 'templates/template.mainmenu'], function (Backbone, _, Marionette, template) {
    "use strict";
    var CategoryView = Marionette.ItemView.extend({

        tagName: 'div',

        template: template['category.layout'],

        id: 'category-layout',

        initialize: function(){
            console.log('Category Layout: initialized');
        },
        onRender: function(){
            console.log(this.model) /// < --- doesn't return anything 
        },
        onShow: function(){
            console.log(this.model) ///< --- doesn't return anything 
        }
    });

    return CategoryView;
});

它仅在我在 CollectionView 之上创建 LayoutView 并从那里处理获取和分配 collection 时才有效。

define([ 'backbone', 'underscore', 'marionette', 
            'templates/template.mainmenu', 
            'collections/MainMenu/MM.collection.categories',
            'layouts/MainMenu/collectionview.categories'    ],
    function (Backbone, _, Marionette, template, c_Categories, cv_Categories) {
    "use strict";
    var CategoryLayoutView = Marionette.LayoutView.extend({


        template: template['categories.layout'],

        regions: {
            categories : '#categories'
        },

        id: 'categories-layout',

        initialize: function(options){
            this.collection = new c_Categories();
            console.log('Category Layout: initialized');
        },

        onRender: function(){
            var categories = this.categories
            var collection = this.collection;
            collection.fetch().done(function(cData){
                categories.show(new cv_Categories({collection : collection}))
            })
        },

        onShow: function(){
        }
    });

    return CategoryLayoutView;
});

如有任何帮助,我们将不胜感激。

谢谢

You need to pass childViewOptions from your collection view.

示例:

define([ 'backbone', 'underscore', 'marionette', 
    'collections/MainMenu/collection.categories' , 
    'layouts/MainMenu/itemview.category'], 
    function (Backbone, _, Marionette, c_Categories, iv_Category) {
    "use strict";
    var CategoriesCollectionView = Marionette.CollectionView.extend({

        tagName: 'div',

        template: null,

        id: 'categories',

        childView: iv_Category,

        collection : new c_Categories(),

        childViewOptions : function(){
            return{
                collection: this.collection
            }
        },

        initialize: function(){
            console.log('Categories Collection: initialized');

            /// or should I call fetch() from within the CV? 
            /// but how do I then pass all the data to ChildView? 
            this.collection.fetch().done(function(){

            })
        },
        onRender: function(){
            console.log(this.collection) ///<-- shows all the JSON data properly
        },
        onShow: function(){
        }
    });

    return CategoriesCollectionView;
});

并且在您的项目视图中,您可以在初始化方法中获取从集合视图传递的每个集合模型。


项目视图中的初始化方法示例:

initialize: function(options){
            console.log('Category Layout: initialized');
            console.log(options.model);
        },

Marionette.CollectionView 示例 - jsfiddle

//Collection View
var CollectionView = Marionette.CollectionView.extend({
    template: "#coll-template",
    childView: MainView,
    itemViewContainer: "#items"
});

//Item View    
var MainView = Marionette.ItemView.extend({
    template: "#sample-template",
    templateHelpers: function() {
        return {
            id: this.model.id
        };
    },
    onDomRefresh: function() {
        console.log("DOM REFRESH OF ITEM");
    }
});

//Creating some models
var model = new Backbone.Model({
    contentPlacement: "here",
    id: 1
});
var model2 = new Backbone.Model({
    contentPlacement: "here",
    id: 2
});
var model3 = new Backbone.Model({
    contentPlacement: "here",
    id: 3
});

//Create collection and resetting it with created models
var collection = new Backbone.Collection();
collection.reset([model, model2, model3]);


var view = new CollectionView({
    collection: collection
});

Prelimnaries:Collection/CompositeView 的主要目的是正确呈现 Backbone.Collection,即将集合模型传递给 CollectionView children ,并渲染那些 children。除了提供 Collection/CompositeView 之外,您没有必要参与——这是关键——一个 pre 填充的集合。

现在,您遇到的问题是您在 CategoriesCollection.initialize() 上执行异步获取(默认情况下所有 AJAX 调用都是异步的)。由于在定义 CategoriesCollectionView 时会调用该初始化(请参阅其 collection 属性),因此在呈现它时提取可能不会及时返回。因此,CollectionView 呈现,但没有找到模型,如果提供了模型,则只呈现 emptyView

你有两个选择:在 LayoutView 中做你正在做的事情(这不仅是我在我的视图中经常做的事情,而且我已经和一些人谈过顶级 Marionette 贡献者,他们也这样做),或同步获取(出于性能原因我不推荐这样做)。

一些提示

  1. CategoriesCollection.initialize() 中删除提取(如果你想保留它,你必须在提取中传递选项 { async: false },以保证数据将在呈现视图时返回。但是,我不建议这样做,因为在等待获取时会阻塞 CPU。

  2. CategoriesCollectionView 定义中删除 CategoriesCollectionView.collection 属性。相反,我们将从 parent LayoutView

  3. 中传递集合
  4. 我建议您使用 .then() 而不是 .done() 作为 Promise 处理程序。两个原因:

    一个。 .then() 更好地处理错误:如果错误不受管理,它将显示堆栈跟踪,并且第二个参数始终可用于实际处理由 Promise 导致的错误。 b. .then() 允许您继续链接。也许不在这个调用中,但在其他一些 Promise 中,您可能希望在调用进入后调用一系列回调。顾名思义,.done() 是回调链的末端

除此之外,您的解决方案是最佳实践。