如何正确存储javascript模板,以便多次实例化

时间:2012-03-23 02:19:40

标签: javascript backbone.js underscore.js

我正在使用Backbone,因此我Underscore来渲染我的模板。我的模板在<script>标签中呈现,然后我使用jQuery来获取他们的html。我的骨干视图如下所示:

App.ItemView = Backbone.View.extend({
    className:'well',

    events: {
        'click .continue': 'handleContinueClick',
    },

    initialize: function() {
        this.template = _.template($("#ItemTemplate").html())
        this.render()
    },

    render: function() {
        $(this.el).html(this.template({model:this.model}))
    },

    handleContinueClick: function(e) {
        alert('Clicked!')
    }
})

我的问题是我只想为这个特定类型的视图只抓取一次html,这样如果我有很多项目,那么每次都不会在html中搜索此模板。< / p>

基本上我如何在ItemView对象级别(不是视图的实例)正确存储模板变量,记住html的检索必须等到页面加载后(这样我才能保证)模板html可用。)

6 个答案:

答案 0 :(得分:16)

您可以构建一个非常简单的对象来缓存模板:


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;
  }
}

然后在您的视图中,您可以致电TemplateCache.get并传入模板选择器。


Backbone.View.extend({
  template: "#ItemTemplate",

  render: function(){
    var template = TemplateCache.get(this.template);
    var html = template(this.model.toJSON());
    this.$el.html(html);
  }
});

第一次为给定的选择器调用TemplateCache.get时,它将从DOM加载它。获取模板的任何后续调用都将从缓存版本加载它,并阻止额外的DOM访问调用。

FWIW:我在Backbone.Marionette框架中有一个更强大的TemplateCache对象版本:https://github.com/derickbailey/backbone.marionette

答案 1 :(得分:5)

我见过的大多数Backbone示例都是这样做的。这只会在页面完成加载时遍历DOM一次以解析模板,并为每个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

答案 2 :(得分:1)

您可以手动使用prototype.template,并在第一次创建视图实例时编译模板。像这样:

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

演示:http://jsfiddle.net/ambiguous/e6y3F/

诀窍是让你的右手prototype

答案 3 :(得分:1)

您可以将已编译的模板存储在闭包中,以便只有ItemView的实例可以访问它:

(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!');
        }

    });

})();

答案 4 :(得分:1)

使用原型的另一种解决方案:

 initialize: function(option) {
     if (!this.template) App.ItemView.prototype.template = this.template || _.template($('ItemTemplate').html());
 }

答案 5 :(得分:0)

您可以使用原始HTML代码,也可以从DOM-element获取应该在此脚本之前呈现的HTML代码

1)原始HTML代码:

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)或来自呈现DOM元素的HTML代码:

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;
    }
});