我是骨干的新手,我有一组对象和一个将它们显示为列表的视图。它被设置为每次将对象添加到集合时都会重新呈现视图。这是非常低效的,因为如果我一次向集合中添加20个东西,当它只需要在添加最后一个项目后再渲染一次时,它将呈现20次。在完成向集合中添加内容之前,如何使骨架延迟渲染?
这是我的代码:
<html>
<head>
<meta charset="utf-8" />
<title>Looking At Underscore.js Templates</title>
</head>
<body>
<script type="text/template" class="template">
<ul id="petlist">
<% _.each(model.pets, function(pet) { %>
<li><%- pet.name %> (<%- pet.type %>)</li>
<% }); %>
</ul>
</script>
<div id="container"/>
<script type="text/javascript" src="http://code.jquery.com/jquery-1.9.1.js"></script>
<script type="text/javascript" src="http://underscorejs.org/underscore.js"></script>
<script src="http://backbonejs.org/backbone-min.js"></script>
<script type="text/javascript">
var serviceData = [
{
name: "Peaches",
type: "dog"
},
{
name: "Wellington",
type: "cat"
},
{
name: "Beefy",
type: "dog"
}
];
$(document).ready(function() {
var Pet = Backbone.Model.extend({
name: null,
type: null
});
var Pets = Backbone.Collection.extend();
var AppView = Backbone.View.extend({
updateUi: function(model) {
_.templateSettings.variable = "model";
var template = _.template($("script.template").html());
var model = { pets: model.collection.toJSON() };
var html = template(model);
$("#container").html(html);
}
});
var pets = new Pets();
var av = new AppView();
pets.bind("add", av.updateUi);
pets.set(serviceData);
});
</script>
</body>
</html>
答案 0 :(得分:3)
你也可以创建一个额外的方法,比方说,添加。 因此,如果添加新对象,应用程序只会添加一个对象,而不是再次渲染孔集合。
某些人喜欢这样:App.Model = Backbone.Model.extend();
App.Collection = Backbone.Collection.extend({
model: App.Model
});
App.CollectionView = Backbone.View.extend({
tagName: 'ul',
render: function(){
this.collection.each(function(model){
var objView = new App.ModelView({ model: model });
this.$el.append( objView.render().el );
});
return this;
},
showAddForm: function(){
// Here you show the form to add another object to the collection
},
save: function(){
// Take form's data into an object/array, then add it to the collection
var formData = {
type: $('select[name=type]').val(),
name $('input[name=name]').val()
};
// Once added to the collection, take the object/array and...
this.addElement(formData);
},
addElement: function(model){
var modView = new App.ModelView({ model: model });
this.$el.append( modView.render().el );
}
});
App.ModelView = Backbone.View.extend({
tagName: 'li',
template: _.template( "<li><%= name %> (<%= type %>)</li>" ),
render: function(){
this.$el.html( this.template( this.model.toJSON() ) );
return this;
}
});
你明白了吗? 渲染孔集合时,collectionView渲染方法为每个对象/宠物调用modelView。 因此,这样,当您获得新宠物/对象的信息时,您只需创建一个ModelView实例,并将其附加到实际渲染视图。
希望它有所帮助。
答案 1 :(得分:1)
你也可以这样做:
pets.set(serviceData, { silent: true });
pets.trigger('add', pets);
修改av.updateUi以使用整个集合并立即创建HTML,但在这种情况下,'reset'事件可能比'add'更合适。
答案 2 :(得分:1)
您需要在代码上重新考虑一些因素。对于您的特定情况,您需要使用reset而不是set,以便在设置数据时仅调度一个事件。您也可以将集合传递给视图,视图可以监听重置事件。
此外,为了防止浏览器的压力,您可以使用document.createDocumentFragment,它是一个加速追加处理的DOM持有者。检查第二点以获得更多参考: http://ozkatz.github.io/avoiding-common-backbonejs-pitfalls.html
<html>
<head>
<meta charset="utf-8" />
<title>Looking At Underscore.js Templates</title>
</head>
<body>
<script type="text/template" class="template">
<ul id="petlist">
<% _.each(model.pets, function(pet) { %>
<li><%- pet.name %> (<%- pet.type %>)</li>
<% }); %>
</ul>
</script>
<div id="container"/>
<script type="text/javascript" src="http://code.jquery.com/jquery-1.9.1.js"></script>
<script type="text/javascript" src="http://underscorejs.org/underscore.js"></script>
<script src="http://backbonejs.org/backbone-min.js"></script>
<script type="text/javascript">
var serviceData = [
{
name: "Peaches",
type: "dog"
},
{
name: "Wellington",
type: "cat"
},
{
name: "Beefy",
type: "dog"
}
];
$(document).ready(function() {
var Pet = Backbone.Model.extend({
name: null,
type: null
});
var Pets = Backbone.Collection.extend();
var AppView = Backbone.View.extend({
initialize : function(){
this.collection.bind("reset", av.updateUi);
},
updateUi: function() {
$items = document.createDocumentFragment();
this.collection.each(function(model){
var itemView = new ItemView({model : model});
$items.append(itemView.el);
itemView.render();
});
$("#container").html($items);
}
});
var pets = new Pets();
var av = new AppView({collection : pets});
pets.reset(serviceData);
});
</script>
</body>
</html>