简体   繁体   English

backbone.js - 集合和视图

[英]backbone.js - collections and views

I understand how to get a collection together, or an individual model. 我理解如何将一个集合或一个单独的模型。 And I can usually get a model's data to display. 我通常可以获得要显示的模型数据。 But I'm not clear at all how to take a collection and get the list of models within that collection to display. 但是我根本不清楚如何拍摄一个集合并获得该集合中的模型列表来显示。

Am I supposed to iterate over the collection and render each model individually? 我应该迭代集合并单独渲染每个模型吗? Is that supposed to be part of the collection's render function? 那应该是集合渲染功能的一部分吗?

Or does the collection just have it's own view and somehow I populate the entire collection data into a view? 或者该集合是否拥有自己的视图,并以某种方式将整个集合数据填充到视图中?

Just speaking generally, what is the normal method to display a list of models? 一般来说,显示模型列表的常规方法是什么?

From my experience, it's the best to keep in your collection view references to each model's view. 根据我的经验,最好在集合视图中保留对每个模型视图的引用。

This snippet from the project I'm currently working on should help you get the idea better: 我正在处理的项目中的这个片段可以帮助您更好地理解这个想法:

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(); 
    }
});

Taking this approach allows you to update views more efficiently (re-rendering one row in the table instead of the whole table). 采用这种方法可以更有效地更新视图(重新渲染表中的一行而不是整个表)。

I think there are two ways to do it. 我认为有两种方法可以做到这一点。

  • Use a view per item, and manipulate the DOM yourself. 每个项目使用一个视图,并自己操作DOM。 This is what the Todos example does. 这就是Todos的例子。 It's a nice way to do things because the event handling for a single model item is clearer. 这是一种很好的做事方式,因为单个模型项的事件处理更清晰。 You also can do one template per item. 您还可以为每个项目执行一个模板。 On the downside, you don't have a single template for the collection view as a whole. 在缺点方面,您没有整个集合视图的单个模板。
  • Use a view for the whole collection. 使用整个集合的视图。 The main advantage here is that you can do more manipulation in your templates. 这里的主要优点是您可以在模板中进行更多操作。 The downside is that you don't have a template per item, so if you've got a heterogeneous collection, you need to switch in the collection view template code -- bletcherous. 缺点是你没有每个项目的模板,所以如果你有一个异构集合,你需要切换集合视图模板代码 - bletcherous。

For the second strategy, I've done code that works something like this: 对于第二个策略,我已经完成了类似这样的代码:

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();
}});

The template code would look something like this: 模板代码看起来像这样:

  <script type="text/template" id="gaggle-template">
  <ul id="gaggle-list">
  <% _.each(gaggle, function(goose) { %>
     <li><%- goose.name %></li>
  <% }); %>
  </ul>
  </script>

Note that I use the _ functions (useful!) in the template. 请注意,我在模板中使用_ functions(有用!)。 I also use the "obj" element, which is captured in the template function. 我还使用了“obj”元素,它在模板函数中捕获。 It's probably cheating a bit; 它可能有点作弊; passing in {gaggle: [...]} might be nicer, and less dependent on the implementation. 传入{gaggle:[...]}可能更好,而且更少依赖于实现。

I think when it comes down to it the answer is "There are two ways to do it, and neither one is that great." 我认为当谈到它时,答案是“有两种方法可以做到,而且没有一种方法可以做到这一点。”

The idea of backbone is that view rendering is event driven. 骨干的想法是视图渲染是事件驱动的。

Views attach to Model data change events so that when any data in the model changes the view updates itself for you. 视图附加到模型数据更改事件,以便当模型中的任何数据更改时,视图会自动更新。

What you're meant to do with collections is manipulate a collection of models at the same time. 您对集合的意图是同时操作一组模型。

I would recommend reading the annotated example . 我建议阅读带注释的例子

I've also found this a confusing part of the Backbone framework. 我还发现这是Backbone框架的一个令人困惑的部分。

The example Todos code is an example here. 示例Todos代码就是一个例子。 It uses 4 classes: 它使用4个类:

  • Todo (extends Backbone.Model). Todo (扩展Backbone.Model)。 This represents a single item to be todone. 这表示单个项目是todone。
  • TodoList (extends Backbone.Collection). TodoList (扩展Backbone.Collection)。 Its "model" property is the Todo class. 它的“模型”属性是Todo类。
  • TodoView (extends Backbone.View). TodoView (扩展Backbone.View)。 Its tagName is "li". 它的tagName是“li”。 It uses a template to render a single Todo. 它使用模板渲染单个Todo。
  • AppView (extends Backbone.View). AppView (扩展Backbone.View)。 Its element is the "#todoapp" . 它的元素是“#todoapp”。 Instead of having a "model" property, it uses a global TodoList named "Todos" (it's not clear why...). 它不使用“模型”属性,而是使用名为“Todos”的全局TodoList(不清楚为什么......)。 It binds to the important change events on Todos, and when there's a change, it either adds a single TodoView, or loops through all the Todo instances, adding one TodoView at a time. 它与Todos上的重要变化事件有关,当有变化时,它要么添加一个TodoView,要么循环遍历所有Todo实例,一次添加一个TodoView。 It doesn't have a single template for rendering; 它没有一个用于渲染的模板; it lets each TodoView render itself, and it has a separate template for rendering the stats area. 它让每个TodoView自我渲染,它有一个单独的模板来渲染统计区域。

It's not really the world's best example for first review. 这不是第一次审查的世界上最好的例子。 In particular, it doesn't use the Router class to route URLs, nor does it map the model classes to REST resources. 特别是,它不使用Router类来路由URL,也不将模型类映射到REST资源。

But it seems like the "best practice" might be to keep a view for each member of the collection, and manipulate the DOM elements created by those views directly. 但似乎“最佳实践”可能是为集合的每个成员保留一个视图,并直接操作这些视图创建的DOM元素。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM