每次使用模板时都要编译它们

Compiling templates every time I use them

本文关键字:编译      更新时间:2023-09-26

我使用Backbone、Requirejs和Handlebars来管理我的前端结构。然而,我遇到了一个颠簸。考虑以下片段:

render: function() {
    var template = Handlebars.compile(TestViewTemplate);
    var srchtml = template({
        test: 'hello'
    });
    this.$el.html(srchtml); 
}

假设此视图在网站中多次渲染,并多次执行渲染功能。调用.compile方法会导致每次都需要"重新编译"视图的开销吗?还是Handlebars每次编译时都会保存模板的缓存副本?我是否应该将Context对象传递给我的所有View模块,在那里我保存编译的模板,并检查模板是否已经编译,如果已经编译,请使用已经编译的模板并渲染它?

有标准的方法来处理这个问题吗?

我对Handlebars真的很新鲜,任何建议都非常感谢!

这不是你想要的完整答案,但对于评论来说有点太多了-虽然没有完全消除开销,但在创建视图时,我的常规方法是声明一个属性模板,即编译后的模板。这样,它只会在创建时进行编译。

var ModelView = Backbone.View.extend({
    //get the template and cache it for future use
    template: Handlebars.compile(templateName),
    initialize: function() {
    },
    //render this view with the models data
    render: function() {
        //attach the generated template to this views $el
        this.$el.html(this.template(this.model.toJSON()));
        return this;
    },

});

重新呈现同一视图时,该视图已引用了已编译的模板。但这并不能掩盖这样一个事实,即这种类型的每个新视图都将编译

所以我找到了一个更持久的解决方案,并希望与其他人分享我的做法。

我创建了一个Context对象,它只实例化一次,并在整个应用程序中传递。这就是它的样子:

define([
    'jquery',
    'handlebars'
], function($, Handlebars) {
    this.ctx = this.ctx || new function(options) {
        if( typeof options === 'undefined' ) options = {};
        /**
         * introducing a _this variable that holds scope to the base object.
         */
        var _this = this;
        /**
         * Keeps track of whether the Context has been initialized or not,
         * prevents double initialization.
         */
        var initialized = false;
        var initHelpers = function() {
            Handlebars.registerHelper('ifeq', function(v1, v2, options) {
                return (v1 === v2) ? options.fn(this) : options.inverse(this);
            });
        }
        this.init = function(options) {
            if( initialized ) {
                console.log('Prevented an attempt at initializing the Context object twice.');
                return;
            }
            /* Setting the debug variable, look at the declaration above in the implementation
             * for more information about this. */
            debug = options.debug || false;
            /**
             * Initializing the Handlebars helpers, necessary for the template rendering.
             */
            initHelpers();
        }
        // Functionality for the template caching methods. //
        var hbsTemplates = {};
        this.getTemplate = function(name, templateHtml) {
            return hbsTemplates[name] || function() {
                var compiledTemplate = Handlebars.compile(templateHtml);
                hbsTemplates[name] = compiledTemplate;
                return compiledTemplate;
            }();
        }
    }
    return this.ctx;
});

我们还必须启动它,最好是尽快启动。

Context.init({
    /* Options */
});

当我创建主干视图时,我声明以下变量:

template: Context.getTemplate('mywidget.mytemplate', FloorViewTemplate),

请注意作为第一个参数传递的字符串。这是用来引用Context对象中HashMap中的模板的,我用文件夹结构来表示。在这种情况下,它是mywidget/mytemplate.hbs,表示为mywidget.mytemplate

记住,在这一点上,Context对象已经作为任何其他类型的被提取

define([
    'Context'
], function(Context) {
});

最后,我们得到模板并提供我们的参数。

var html = this.template({
    arg1: 1,
    arg2: 2
});

现在只需要将html添加到DOM中。

这很好用。如果有人对如何更有效地做到这一点有任何其他想法,请编辑答案。