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

javascript - Backbone refresh view events - Stack Overflow

programmeradmin3浏览0评论

In my view I don't declare this.el because I create it dinamically, but in this way the events don't fire.

This is the code:

View 1:

App.Views_1 = Backbone.View.extend({

    el:             '#content',

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

    render:         function() {    
                        this.model.each(this.renderSingle);                 
                    },

    renderSingle:   function(model) {

                        this.tmpView = new App.Views_2({model: model});                     
                        $(this.el).append( this.tmpView.render().el );

                    }
});

View 2:

App.Views_2 = Backbone.View.extend({

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

    render:         function() {    
                        this.el = $('#template').tmpl(this.model.attributes);       // jQuery template                          
                        return this;                            
                    },

    events:         {       
                        'click .button' :       'test'                  
                    },

    test:           function() {        
                        alert('Fire');  
                    }

    });

});

When I click on ".button" nothing happens. Thanks;

In my view I don't declare this.el because I create it dinamically, but in this way the events don't fire.

This is the code:

View 1:

App.Views_1 = Backbone.View.extend({

    el:             '#content',

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

    render:         function() {    
                        this.model.each(this.renderSingle);                 
                    },

    renderSingle:   function(model) {

                        this.tmpView = new App.Views_2({model: model});                     
                        $(this.el).append( this.tmpView.render().el );

                    }
});

View 2:

App.Views_2 = Backbone.View.extend({

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

    render:         function() {    
                        this.el = $('#template').tmpl(this.model.attributes);       // jQuery template                          
                        return this;                            
                    },

    events:         {       
                        'click .button' :       'test'                  
                    },

    test:           function() {        
                        alert('Fire');  
                    }

    });

});

When I click on ".button" nothing happens. Thanks;

Share Improve this question asked Aug 31, 2011 at 17:03 keepyourwebkeepyourweb 6624 gold badges11 silver badges19 bronze badges 1
  • assuming the #template contains a button with a class of '.button', this should work. can you post the contents of your #template? – Derick Bailey Commented Sep 1, 2011 at 15:07
Add a comment  | 

2 Answers 2

Reset to default 20

At the end of your render() method, you can tell backbone to rebind events using delegateEvents(). If you don't pass in any arguments, it will use your events hash.

render:         function() {    
                    this.el = $('#template').tmpl(this.model.attributes);       // jQuery template                          
                    this.delegateEvents();
                    return this;                            
                }

As of Backbone.js v0.9.0 (Jan. 30, 2012), there is the setElement method to switching a views element and manages the event delegation.

render: function() {
    this.setElement($('#template').tmpl(this.model.attributes));
    return this;
}

Backbone.View setElement: http://backbonejs.org/#View-setElement

setElementview.setElement(element)

If you'd like to apply a Backbone view to a different DOM element, use setElement, which will also create the cached $el reference and move the view's delegated events from the old element to the new one.



Dynamically creating your views in this fashion has it's pros and cons, though:

Pros:

  • All of your application's HTML markup would be generated in templates, because the Views root elements are all replaced by the markup returned from the rendering. This is actually kind of nice... no more looking for HTML inside of JS.
  • Nice separation of concerns. Templates generate 100% of HTML markup. Views only display states of that markup and respond to various events.
  • Having render be responsible for the creation of the entire view (including it's root element) is in line with the way that ReactJS renders components, so this could be a beneficial step in the process of migrating from Backbone.Views to ReactJS components.

Cons: - these are mostly negligible

  • This wouldn't be a painless transition to make on an existing code base. Views would need to be updated and all templates would need to have the View's root elements included in the markup.
    • Templates used by multiple views could get a little hairy - Would the root element be identical in all use cases?
  • Prior to render being called, the view's root element is useless. Any modifications to it will be thrown away.
    • This would include parent views setting classes/data on child view elements prior to rendering. It is also bad practice to do this, but it happens -- those modifications will be lost once render overrides the element.
  • Unless you override the Backbone.View constructor, every view will unnecessarily delegate it's events and set attributes to a root element that is replaced during rendering.
  • If one of your templates resolves to a list of elements rather than a single parent element containing children, you're going have a bad time. setElement will grab the first element from that list and throw away the rest.
    • Here's an example of that problem, though: http://jsfiddle.net/CoryDanielson/Lj3r85ew/
    • This problem could be mitigated via a build task that parses the templates and ensures they resolve to a single element, or by overriding setElement and ensuring that the incoming element.length === 1.
发布评论

评论列表(0)

  1. 暂无评论