【问题标题】:Compiling templates every time I use them每次使用模板时都要编译
【发布时间】:2014-09-24 15:59:00
【问题描述】:

我正在使用 Backbone、Requirejs 和 Handlebars 来管理我的前端结构。但是我遇到了一个颠簸。考虑以下 sn-p:

render: function() {

    var template = Handlebars.compile(TestViewTemplate);
    var srchtml = template({
        test: 'hello'
    });

    this.$el.html(srchtml); 
}

假设这个视图在网站中被多次渲染,多次执行渲染函数。调用 .compile 方法是否会导致开销,因为每次都需要“重新编译”视图,或者 Handlebars 是否会在每次编译时保存模板的缓存副本?我是否应该将一个 Context 对象传递给我保存已编译模板的所有视图模块,并检查模板是否已经编译,如果是,使用已经编译的并渲染它?

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

我对 Handlebars 非常陌生,非常感谢任何建议!

【问题讨论】:

标签: javascript backbone.js requirejs handlebars.js


【解决方案1】:

这不是您要寻找的完整答案,但评论有点过多 - 虽然没有完全消除开销,但我在创建视图时的常规方法是声明一个属性模板,它是已编译的模板。这样它只会在创建时编译。

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


});

重新渲染同一个视图时,它已经引用了已编译的模板。但这并不能克服这种类型的每个新视图都会编译的事实

【讨论】:

  • 感谢您的输入,这基本上就是我所追求的,但我还没有找到缓存模板的方法。一旦找到更持久的解决方案,我将回到这个线程。
  • 正如@Evgeniy marionette 所建议的那样具有此功能,即使您不使用所有marionette 所提供的功能,它也为视图和嵌套视图提供了一个很好的结构
【解决方案2】:

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

我创建了一个仅实例化一次并在整个应用程序中传递的 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 即可。

这很好用。如果有人对如何更有效地执行此操作有任何其他想法,请编辑答案。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-02-25
    • 2020-08-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多