1

我是骨干新手,我有一个对象集合和一个将它们显示为列表的视图。它被设置为每次将对象添加到集合中时都会重新呈现视图。这确实是低效的,因为如果我一次向集合中添加 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>
4

3 回答 3

4

您还可以创建一个名为 add 的额外方法。因此,如果您添加一个新对象,应用程序只会添加一个对象,而不是再次渲染孔集合。

像这样的东西:

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 实例,并将其附加到实际渲染的视图中。

希望能帮助到你。

于 2013-04-05T20:37:36.550 回答
1

你也可以这样做:

pets.set(serviceData, { silent: true });
pets.trigger('add', pets);

并修改 av.updateUi 以使用整个集合并立即创建 HTML,但在这种情况下,“重置”事件可能比“添加”更合适。

于 2013-04-05T20:49:15.467 回答
1

你需要在你的代码中重新考虑一些事情。对于您的特定情况,您需要使用重置而不是设置,以便在设置数据时仅调度一个事件。您也可以将集合传递给视图,并且视图可以侦听重置事件。

此外,为了防止浏览器的压力,您可以使用 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>
于 2013-04-06T19:31:06.870 回答