How do I properly store a javascript template, so that it isn't instantiated multiple times

后端 未结 6 383
一整个雨季
一整个雨季 2021-02-03 12:44

I\'m using Backbone and therefore Underscore to render my templates. My templates get rendered in

相关标签:
6条回答
  • 2021-02-03 12:55

    Another solution using prototype:

     initialize: function(option) {
         if (!this.template) App.ItemView.prototype.template = this.template || _.template($('ItemTemplate').html());
     }
    
    0 讨论(0)
  • 2021-02-03 12:56

    Most Backbone examples I've seen do it like this. This will only traverse the DOM once to parse the template when the page finishes loading and use that for each new ItemView().

    App.ItemView = Backbone.View.extend({
        template: _.template($("#ItemTemplate").html()),
    
        className:'well',
    
        events: {
            'click .continue': 'handleContinueClick',
        },
    
        ...
    });
    

    http://backbonejs.org/docs/todos.html#section-21

    0 讨论(0)
  • 2021-02-03 12:59

    You could store the compiled template in a closure so that only the instances of ItemView can access it:

    (function() {
    
        var template;
    
        App.ItemView = Backbone.View.extend({
    
            className:'well',
    
            events: {
                'click .continue': 'handleContinueClick'
            },
    
            initialize: function() {
                this.render();
            },
    
            render: function() {
                template = template || _.template($("#ItemTemplate").html());
                $(this.el).html(template({model:this.model}));
            },
    
            handleContinueClick: function(e) {
                alert('Clicked!');
            }
    
        });
    
    })();
    
    0 讨论(0)
  • 2021-02-03 13:01

    You could use raw HTML-code or you might get HTML-code from DOM-element which should had rendered before this script

    1) raw HTML-code:

    var app = app || {};
    
    app.TreeView = Backbone.View.extend({
        tagName: 'ul',
        id: 'js-tree',
        template: _.template('<li data-id="<%- id %>"><%- Name %></li>'),
        initialize: function() {
            this.render();
        },
        render: function () {
            this.model.each(this.renderRow, this);
            return this;
        },
        renderRow: function(model) {
            var html = template(model);
            this.$el.append(html);
            return this;
        }
    });
    

    2) or HTML-code from rendered DOM-element:

    var app = app || {};
    
    app.TreeView = Backbone.View.extend({
        tagName: 'ul',
        id: 'js-tree',
        template: _.template($("#js-template-tree-item").html()),
        initialize: function() {
            this.render();
        },
        render: function () {
            this.model.each(this.renderRow, this);
            return this;
        },
        renderRow: function(model) {
            var html = template(model);
            this.$el.append(html);
            return this;
        }
    });
    
    0 讨论(0)
  • 2021-02-03 13:06

    You could muck around with prototype.template by hand and compile the template the first time you create an instance of your view. Something like this:

    initialize: function() {
        if(!this.constructor.prototype.template)
            this.constructor.prototype.template = _.template($("#ItemTemplate").html());
        this.render();
    }
    

    Demo: http://jsfiddle.net/ambiguous/e6y3F/

    The trick is to get your hands on the right prototype.

    0 讨论(0)
  • 2021-02-03 13:15

    You can build a very simple object that caches the templates for you:

    
    TemplateCache = {
      get: function(selector){
        if (!this.templates){ this.templates = {}; }
    
        var template = this.templates[selector];
        if (!template){
          var tmpl = $(selector).html();
          template = _.template(tmpl);
          this.templates[selector] = template;
        }
    
        return template;
      }
    }
    

    Then in your view, you can call TemplateCache.get and pass in your template selector.

    
    Backbone.View.extend({
      template: "#ItemTemplate",
    
      render: function(){
        var template = TemplateCache.get(this.template);
        var html = template(this.model.toJSON());
        this.$el.html(html);
      }
    });
    

    The first time you call TemplateCache.get for a given selector, it will load it from the DOM. Any subsequent calls to get the template will load it from the cached version and prevent the extra DOM access call.

    FWIW: I have a much more robust version of the TemplateCache object in my Backbone.Marionette framework: https://github.com/derickbailey/backbone.marionette

    0 讨论(0)
提交回复
热议问题