如何正确存储javascript模板,使其不会;t实例化了多次

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

本文关键字:实例化 存储 何正确 javascript 模板      更新时间:2023-09-26

我使用Backbone,因此使用Undercore来渲染我的模板。我的模板在<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中搜索这个模板。

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

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


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

我见过的大多数骨干示例都是这样做的。这将只遍历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

您可以手动处理prototype.template,并在第一次创建视图实例时编译模板。类似这样的东西:

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

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

诀窍是拿到正确的prototype

您可以将编译后的模板存储在闭包中,这样只有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!');
        }
    });
})();

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

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

您可以使用原始HTML代码,也可以从DOM元素中获取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;
    }
});