Javascript backbone.js-集合和视图

Javascript backbone.js-集合和视图,javascript,jquery,backbone.js,mustache,Javascript,Jquery,Backbone.js,Mustache,我知道如何收集一个集合,或一个单独的模型。我通常可以得到一个模型的数据来显示。但我完全不清楚如何获取一个集合并显示该集合中的模型列表 我应该迭代集合并分别渲染每个模型吗? 这应该是集合的渲染功能的一部分吗 还是说集合只有自己的视图,而我以某种方式将整个集合数据填充到一个视图中 一般来说,显示模型列表的常规方法是什么?主干的思想是视图渲染是事件驱动的 视图附加到模型数据更改事件,以便当模型中的任何数据更改时,视图会自动更新 使用集合的目的是同时操作模型集合 我建议您阅读。根据我的经验,最好在收藏视

我知道如何收集一个集合,或一个单独的模型。我通常可以得到一个模型的数据来显示。但我完全不清楚如何获取一个集合并显示该集合中的模型列表

我应该迭代集合并分别渲染每个模型吗? 这应该是集合的渲染功能的一部分吗

还是说集合只有自己的视图,而我以某种方式将整个集合数据填充到一个视图中


一般来说,显示模型列表的常规方法是什么?

主干的思想是视图渲染是事件驱动的

视图附加到模型数据更改事件,以便当模型中的任何数据更改时,视图会自动更新

使用集合的目的是同时操作模型集合


我建议您阅读。

根据我的经验,最好在收藏视图中保留对每个模型视图的引用

我目前正在进行的项目中的这个片段应该可以帮助您更好地理解这个想法:

var MyElementsViewClass = Backbone.View.extend({
    tagName: 'table',

    events: {
        // only whole collection events (like table sorting)
        // each child view has it's own events
    },
    initialize: function() {
        this._MyElementViews = {}; // view chache for further reuse
        _(this).bindAll('add');
        this.collection.bind('add', this.add);
    },
    render: function() {
        // some collection rendering related stuff
        // like appending <table> or <ul> elements

        return this;
    },
    add: function(m) {
        var MyElementView = new MyElementViewClass({
            model: m
        });

        // cache the view
        this._MyElementViews[m.get('id')] = MyElementView;

        // single model rendering
        // like appending <tr> or <li> elements
        MyElementView.render(); 
    }
});
var MyElementsViewClass=Backbone.View.extend({
标记名:“表”,
活动:{
//仅整个集合事件(如表排序)
//每个子视图都有自己的事件
},
初始化:函数(){
此._MyElementViews={};//查看chache以供进一步重用
_(本)。bindAll(“添加”);
this.collection.bind('add',this.add));
},
render:function(){
//一些与渲染相关的东西
//类似于附加或
    元素 归还这个; }, 加:功能(m){ var MyElementView=新的MyElementViewClass({ 型号:m }); //缓存视图 这._MyElementViews[m.get('id')]=MyElementView; //单模型渲染 //类似于附加或
  • 元素 MyElementView.render(); } });

采用这种方法可以更有效地更新视图(重新呈现表中的一行而不是整个表)。

我还发现这是主干框架中令人困惑的部分

Todos代码示例就是这里的一个示例。它使用4个类:

  • Todo(扩展主干网.Model)。这表示要删除的单个项
  • TodoList(扩展主干网.Collection)。它的“model”属性是Todo类
  • 提供查看(扩展主干.View)。它的标记名是“li”。它使用模板来呈现单个Todo
  • AppView(扩展主干.View)。它的元素是“todoapp”。它没有“model”属性,而是使用名为“Todos”的全局TodoList(不清楚为什么…)。它绑定到Todo上的重要更改事件,当发生更改时,它要么添加一个TodoView,要么遍历所有Todo实例,一次添加一个TodoView。它没有用于渲染的单个模板;它允许每个TodoView自己进行渲染,并且有一个单独的模板用于渲染统计区域
这并不是世界上第一次审查的最好例子。特别是,它不使用Router类来路由URL,也不将模型类映射到REST资源


但“最佳实践”似乎是为集合的每个成员保留一个视图,并直接操作由这些视图创建的DOM元素。

我认为有两种方法可以做到这一点

  • 对每个项目使用一个视图,并自己操作DOM。这就是Todos示例所做的。这是一种很好的方法,因为单个模型项的事件处理更清晰。您还可以为每个项目创建一个模板。缺点是,集合视图作为一个整体没有一个模板
  • 对整个集合使用视图。这里的主要优点是,您可以在模板中进行更多操作。缺点是您没有每个项的模板,因此如果您有一个异构集合,则需要切换集合视图模板代码--Bletchrous
对于第二种策略,我编写了如下代码:

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

var Gaggle = Backbone.Collection.extend({
   model: Goose;
};

var GaggleView = Backbone.View.extend({
    el: $('#gaggle'),
    template: _.template($('#gaggle-template').html()),
    render: function() {
        $(this.el).html(this.template(this.model.toJSON()));
    }
};

var g = new Gaggle({id: 69);

g.fetch({success: function(g, response) {
    gv = new GaggleView({model: g});
    gv.render();
}});
  <script type="text/template" id="gaggle-template">
  <ul id="gaggle-list">
  <% _.each(gaggle, function(goose) { %>
     <li><%- goose.name %></li>
  <% }); %>
  </ul>
  </script>
模板代码如下所示:

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

var Gaggle = Backbone.Collection.extend({
   model: Goose;
};

var GaggleView = Backbone.View.extend({
    el: $('#gaggle'),
    template: _.template($('#gaggle-template').html()),
    render: function() {
        $(this.el).html(this.template(this.model.toJSON()));
    }
};

var g = new Gaggle({id: 69);

g.fetch({success: function(g, response) {
    gv = new GaggleView({model: g});
    gv.render();
}});
  <script type="text/template" id="gaggle-template">
  <ul id="gaggle-list">
  <% _.each(gaggle, function(goose) { %>
     <li><%- goose.name %></li>
  <% }); %>
  </ul>
  </script>

注意,我在模板中使用了u函数(有用!)。我还使用了模板函数中捕获的“obj”元素。这可能有点作弊;传入{gaggle:[…]}可能更好,而且对实现的依赖性更小


我认为,归根结底,答案是“有两种方法可以做到这一点,但两种方法都没有那么好。”

我建议您将这些MyElementView“缓存”到集合对象中。我很难做到这一点——我理解主要思想,也许我只是对初始化函数、事件绑定感到困惑。fetch()不会触发“添加”事件,对吗?当获取集合时,是否应该有更新视图的方法?或者我应该在initialize函数中手动“添加”每个模型?@Raynos,为什么要在集合对象中?别介意这个建议。虽然我确实认为整个方法应该是集合/模型驱动的。@pawlik,但我不能建议编辑,因为它不是6个字符长,而是
这个应该是
这个。虽然第二种方法的代码更少,但我不喜欢集合视图中对集合实例名称的引用是硬编码的。(
AppView.addAll
中的
Todo
)我想这就是需要
\ucode>.bindAll
的地方。为了理解这一点,我最终遇到了相同的问题。看看这家伙的解决方案,它解决了我自己的很多问题: