backbone js, Update view on model change

2019-02-01 13:57发布

Why my view is not getting updated?

    <html>

     <script src="./jquery.js"></script>
     <script src="./underscore-min.js"></script>
     <script src="./backbone.js"></script>

     <style>
        table,td {border:1px solid #000;}
     </style>

     <body>
     </body>

     <script>

     var rowTemplate="<tr><td class='name'><%= name %></td><td class='age'><%= age %></td><td class='name'><%= name %></td><td class='age'><%= age %></td><td class='name'><%= name %></td><td class='age'><%= age %></td><td class='name'><%= name %></td><td class='age'><%= age %></td><td class='name'><%= name %></td><td class='age'><%= age %></td><td class='name'><%= name %></td><td class='age'><%= age %></td><td class='name'><%= name %></td><td class='age'><%= age %></td><td class='name'><%= name %></td><td class='age'><%= age %></td><td class='name'><%= name %></td><td class='age'><%= age %></td><td class='name'><%= name %></td><td class='age'><%= age %></td><td class='name'><%= name %></td><td class='age'><%= age %></td><td class='name'><%= name %></td><td class='age'><%= age %></td><td class='name'><%= name %></td><td class='age'><%= age %></td><td class='name'><%= name %></td><td class='age'><%= age %></td><td class='name'><%= name %></td><td class='age'><%= age %></td><td class='name'><%= name %></td><td class='age'><%= age %></td><td class='name'><%= name %></td><td class='age'><%= age %></td></tr>";

     /** View representing a table */
     var TableView = Backbone.View.extend({

         tagName: 'table',

         initialize : function() {
             _.bindAll(this,'render','renderOne');
             if(this.model) {
              this.model.on('change',this.render,this);
              console.log(this.model);
             }
         },

         render: function() {
             this.collection.each(this.renderOne);
             return this;
         },

         renderOne : function(model) {
             var row=new RowView({model:model});
             this.$el.append(row.render().$el);
             return this;
         }
     });

     /** View representing a row of that table */
     var RowView = Backbone.View.extend({  
         events: {
             "click .age": function() {console.log(this.model.get("name"));}
         },

         render: function() {
             var html=_.template(rowTemplate,this.model.toJSON());
             this.setElement( $(html) );
             return this;
         },

         update : function() {

         }
     });

     var data = [
         {'name': 'Oli', 'age': 25},
         {'name': 'Oli', 'age': 25},

         ];

     /** Collection of models to draw */
     var peopleCollection = new Backbone.Collection(data);
     var tableView = new TableView({collection: peopleCollection});
     $("body").append( tableView.render().$el );

     console.log(peopleCollection.models[0].set({'name': 'VJY', 'age': 25}));
     console.log(peopleCollection.models[0]);

     </script>

     </html>

3条回答
何必那么认真
2楼-- · 2019-02-01 14:28

Because your TableView.initialize is accessing this.model but you're passing it a collection instead?

查看更多
祖国的老花朵
3楼-- · 2019-02-01 14:33

You were missing a few things.

  • The row template should only render one row. The Table template repeats it in collection.each().
  • You needed to specify which model the View was tied to. Now, when the model is changed, the View "listens to" that event and fires its render action. Note that you didn't specify a model, but the collection auto creates a model for each element in the data array it's passed.
  • You were trying to use setElement for rendering the view. Rendering is as simple as passing your template's HTML to the jQuery object which is auto created by the view (this.$el in code below).
<html>
    <script src="./jquery.js"></script>
    <script src="./underscore.js"></script>
    <script src="./backbone.js"></script>
    <style>
        table,
        td {
            border: 1px solid #000;
        }
    </style>
    <body></body>
    <script>
        var rowTemplate = "<tr><td class='name'><%= name %></td><td class='age'><%= age %></td></tr>";

        var data = [
                {
                    'name': 'Bert',
                    'age' : 6
                }, {
                    'name': 'Ernie',
                    'age' : 7
                }
            ];

        /** Collection of models to draw */
        var peopleCollection = new Backbone.Collection(data);

        /** View representing a table */
        var TableView = Backbone.View.extend({
                tagName: 'table',
                initialize: function () {
                    _.bindAll(this, 'render', 'renderOne');
                    if (this.model) {
                        this.model.on('change', this.render, this);
                        console.log(this.model);
                    }
                },
                render: function () {
                    this.collection.each(this.renderOne);
                    return this;
                },
                renderOne: function (model) {
                    var row = new RowView({
                            model: model
                        });
                    this.$el.append(row.render().$el);
                    return this;
                }
            });

        /** View representing a row of that table */
        var RowView = Backbone.View.extend({
                events: {
                    "click .age": function () {
                        console.log(this.model.get("name"));
                    }
                },
                initialize: function () {
                    this.model.on('change', this.render, this);
                },
                model: peopleCollection.models,
                render: function () {
                    var html = _.template(rowTemplate, this.model.toJSON());
                    this.$el.html(html);
                    return this;
                },
            });

        var tableView = new TableView({
                collection: peopleCollection
            });
        $("body").append(tableView.render().$el);

        console.log(peopleCollection.models[0].set({
            'name': 'Statler',
            'age' : 100
        }));
        console.log(peopleCollection.models[0]);
    </script>
</html>
查看更多
The star\"
4楼-- · 2019-02-01 14:33

You need to bind your view on model's change. I'm assuming you want to update RowView when a row is updated. I've rewritten your RowView. This will now listen to your model's change.

var RowView = Backbone.View.extend({  
         events: {
             "click .age": function() {console.log(this.model.get("name"));}
         },
         initialize: function(){
           this.model.on('change', this.render, this);
         },
         render: function() {
             var html=_.template(rowTemplate,this.model.toJSON());
             this.setElement( $(html) );
             return this;
         },

         update : function() {

         }
     });
查看更多
登录 后发表回答