每次我使用它们时编译模板

时间:2014-09-24 15:59:00

标签: javascript backbone.js requirejs handlebars.js

我使用Backbone,Requirejs和Handlebars来管理我的前端结构。但是我碰到了碰撞。请考虑以下代码段:

render: function() {

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

    this.$el.html(srchtml); 
}

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

有没有一种标准的方法可以解决这个问题?

我对Handlebars非常满意,非常感谢任何建议!

2 个答案:

答案 0 :(得分: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;
    },


});

重新渲染相同的视图时,它已经具有对已编译模板的引用。但是,这并没有克服这种类型的每个新视图都将编译

的事实

答案 1 :(得分:0)

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

我创建了一个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 */
});

当我创建一个Backbone View时,我声明了以下变量:

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中即可。

这很好用。如果有人对如何提高效率有任何其他想法,请编辑答案。