最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Backbone.js EL and Template in the View - Stack Overflow

programmeradmin3浏览0评论

So i'm very new to backbone.js and not so good at JavaScript in general, so I was wondering if someone could explain to me why

I cannot define my EL property, and Template property in my view, and then use this.template in my render. Instead I have to define the template and el in my render function.

    var ProductView = Backbone.View.extend({
    el: $('#product-list'),

    initialize: function() { 
            this.el.html('<span style="color:white">loading...</span>'); 
    }, // end initialize


    render: function(collection) { 
    //    // assign the template 
          this.template = $('#product_template');

          // Where the template will be placed  
          this.el = $('#product-list'); 

          // Add the collection to the main object 
          this.collection = collection;

          // add tthe data to the html variable 
          var html = this.template.tmpl(this.collection.toJSON());

          // place the html in the element. 
           this.el.html(html);

           // not even sure what the hell this is. 
          return this;      
        }   // end render  

});

So i'm very new to backbone.js and not so good at JavaScript in general, so I was wondering if someone could explain to me why

I cannot define my EL property, and Template property in my view, and then use this.template in my render. Instead I have to define the template and el in my render function.

    var ProductView = Backbone.View.extend({
    el: $('#product-list'),

    initialize: function() { 
            this.el.html('<span style="color:white">loading...</span>'); 
    }, // end initialize


    render: function(collection) { 
    //    // assign the template 
          this.template = $('#product_template');

          // Where the template will be placed  
          this.el = $('#product-list'); 

          // Add the collection to the main object 
          this.collection = collection;

          // add tthe data to the html variable 
          var html = this.template.tmpl(this.collection.toJSON());

          // place the html in the element. 
           this.el.html(html);

           // not even sure what the hell this is. 
          return this;      
        }   // end render  

});
Share Improve this question edited Oct 26, 2011 at 21:12 mu is too short 435k71 gold badges858 silver badges818 bronze badges asked Oct 26, 2011 at 19:32 GamakGamak 1993 silver badges12 bronze badges 5
  • You don't have to do this. this.el should be set by the time initialize is called (but you should use $(this.el) - el is generally the DOM element, not a jQuery object). You can define the template in initialize if you prefer. Are you getting errors? – nrabinowitz Commented Oct 26, 2011 at 19:37
  • Also, return this; is a Backbone convention that allows chaining, e.g. $(parent).append(view.render().el) - you can't use that last .el in the same statement unless you return the view in .render(). – nrabinowitz Commented Oct 26, 2011 at 19:39
  • The code I have is working for me, but it doesnt look like anything i've seen in the tutorials, so i'm thinking i'm doing something wrong. – Gamak Commented Oct 26, 2011 at 20:53
  • Right, but does it throw some kind of error if you do it the way I describe? – nrabinowitz Commented Oct 26, 2011 at 20:59
  • I'm not getting an error when I do it your way, its just not rendering the collection. And if I do a console.log($(this.el)); inside the render function I get undefined – Gamak Commented Oct 26, 2011 at 21:17
Add a ment  | 

2 Answers 2

Reset to default 7

The problem isn't in the way you're defining el or template, it's in how you're setting the call back. In Workspace, your router, you're setting the callback for your collection refresh event like this:

// Bind the view and collection 
// So when the collection is reset, the view executes the render method
Products.bind("reset", this.view.render); 

The problem is, you're setting a method as a callback, but you're not providing a context object as the third argument to bind - so the method is called, but this in the method refers to the global object, not the view. So this.el is undefined, because it's not looking at the view instance at all. Try:

// Bind the view and collection 
// So when the collection is reset, the view executes the render method
Products.bind("reset", this.view.render, this.view); 

and see how that goes.

(I made a jsFiddle to demonstrate that the el and template were set properly under normal circumstances, though it doesn't actually include the fix above, which is hard to mock up without the server-side data: http://jsfiddle/nrabinowitz/QjgS9/)

You can't do this:

var ProductView = Backbone.View.extend({
    el: $('#product-list'),
    // ...

and get anything useful in el as #product-list probably isn't even present in the DOM when your ProductView is built; so trying to use $('#product-list') for el is simply the classic "I forgot to use $(document).ready()" problem dressed up in Backbone. Using $('#product-list') for el should work if #product-list is around when you define your ProductView though.

You can do this though:

var ProductView = Backbone.View.extend({
    el: '#product-list',
    // ...

and then say $(this.el) when you need to do things inside your view methods. Not only is $(this.el) the usual way of using el but it also works and that's sort of important.

The same issues apply to #product_template.


Looking at your code I see this:

// INstantiate the view 
this.view = new ProductView(); 

// Bind the view and collection 
// So when the collection is reset, the view executes the render method
Products.bind("reset", this.view.render); 

Presumably the render is being triggered by the reset event. But, and this is a big but, the render method isn't bound to the right this anywhere so this won't be the ProductView when render is called and this won't have anything that you expected it to; hence your bizarre "undefined" error.

You could use _.bindAll in your initialize:

initialize: function() {
    _.bindAll(this, 'render');
    // ...

but usually you'd want to give the view a collection when you create it and the view would bind itself to the events so your structure will still be a bit odd.

You can also supply a context (AKA this) when you call bind:

collection.bind('reset', this.render, this);
发布评论

评论列表(0)

  1. 暂无评论