javascript Backbone.js - 集合和视图
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5651629/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
backbone.js - collections and views
提问by Matthew
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?
只是笼统地说,显示模型列表的正常方法是什么?
采纳答案by pawlik
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).
采用这种方法可以更有效地更新视图(重新渲染表中的一行而不是整个表)。
回答by Evan P.
I think there are two ways to do it.
我认为有两种方法可以做到。
- Use a view per item, and manipulate the DOM yourself.This is what the Todos example does. 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.
- 每个项目使用一个视图,并自己操作 DOM。这就是 Todos 示例所做的。这是一种很好的处理方式,因为单个模型项的事件处理更加清晰。您还可以为每个项目制作一个模板。不利的一面是,您没有一个用于整个集合视图的模板。
- 对整个集合使用视图。这里的主要优点是您可以在模板中进行更多操作。缺点是你没有每个项目的模板,所以如果你有一个异构的集合,你需要在集合视图模板代码中切换 - blecherous。
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. I also use the "obj" element, which is captured in the template function. It's probably cheating a bit; passing in {gaggle: [...]} might be nicer, and less dependent on the implementation.
请注意,我在模板中使用了 _ 函数(有用!)。我还使用了在模板函数中捕获的“obj”元素。这可能有点作弊;传入 {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."
我认为归根结底,答案是“有两种方法可以做到,但都不是那么好。”
回答by Raynos
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.
我建议阅读带注释的示例。
回答by Evan P.
I've also found this a confusing part of the Backbone framework.
我还发现这是 Backbone 框架中令人困惑的部分。
The example Todos code is an example here. It uses 4 classes:
Todos 代码示例是此处的示例。它使用 4 个类:
- Todo(extends Backbone.Model). This represents a single item to be todone.
- TodoList(extends Backbone.Collection). Its "model" property is the Todo class.
- TodoView(extends Backbone.View). Its tagName is "li". It uses a template to render a single Todo.
- AppView(extends Backbone.View). Its element is the "#todoapp" . Instead of having a "model" property, it uses a global TodoList named "Todos" (it's not clear why...). 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. 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.
- Todo(扩展 Backbone.Model)。这表示要完成的单个项目。
- TodoList(扩展 Backbone.Collection)。它的“模型”属性是 Todo 类。
- TodoView(扩展 Backbone.View)。它的标签名称是“li”。它使用模板来呈现单个 Todo。
- AppView(扩展 Backbone.View)。它的元素是 "#todoapp" 。它没有使用“模型”属性,而是使用名为“Todos”的全局 TodoList(不清楚为什么......)。它绑定到 Todos 上的重要更改事件,当发生更改时,它要么添加一个 TodoView,要么遍历所有 Todo 实例,一次添加一个 TodoView。它没有用于渲染的单一模板;它让每个 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 元素。