下划线中的外部模板

Tom*_*máš 121 javascript backbone.js underscore.js

我使用的是Underscore模板.可以附加外部文件作为模板吗?

在Backbone View中我有:

 textTemplate: _.template( $('#practice-text-template').html() ),

 initialize: function(){                                            
  this.words = new WordList;            
  this.index = 0;
  this.render();
 },
Run Code Online (Sandbox Code Playgroud)

在我的HTML中是:

<script id="practice-text-template" type="text/template">
   <h3>something code</h3>
</script>
Run Code Online (Sandbox Code Playgroud)

它运作良好.但我需要外部模板.我尝试:

<script id="practice-text-template" type="text/template" src="templates/tmp.js">
Run Code Online (Sandbox Code Playgroud)

要么

textTemplate: _.template( $('#practice-text-template').load('templates/tmp.js') ),
Run Code Online (Sandbox Code Playgroud)

要么

$('#practice-text-template').load('templates/tmp.js', function(data){ this.textTemplate = _.template( data ) })
Run Code Online (Sandbox Code Playgroud)

但它不起作用.

koo*_*hik 107

这是一个简单的解决方案:

var rendered_html = render('mytemplate', {});

function render(tmpl_name, tmpl_data) {
    if ( !render.tmpl_cache ) { 
        render.tmpl_cache = {};
    }

    if ( ! render.tmpl_cache[tmpl_name] ) {
        var tmpl_dir = '/static/templates';
        var tmpl_url = tmpl_dir + '/' + tmpl_name + '.html';

        var tmpl_string;
        $.ajax({
            url: tmpl_url,
            method: 'GET',
            dataType: 'html', //** Must add 
            async: false,
            success: function(data) {
                tmpl_string = data;
            }
        });

        render.tmpl_cache[tmpl_name] = _.template(tmpl_string);
    }

    return render.tmpl_cache[tmpl_name](tmpl_data);
}
Run Code Online (Sandbox Code Playgroud)

在这里使用"async:false"并不是一个坏方法,因为无论如何你必须等到模板加载.

所以,"渲染"功能

  1. 允许您将每个模板存储在静态目录中的单独html文件中
  2. 非常轻巧
  3. 编译和缓存模板
  4. 摘要模板加载逻辑.例如,将来您可以使用预加载和预编译的模板.
  5. 很容易使用

[我正在编辑答案而不是发表评论,因为我认为这很重要.]

如果模板没有显示在本机应用程序中,你看HIERARCHY_REQUEST_ERROR: DOM Exception 3,请看Dave Robinson的答案,究竟是什么导致"HIERARCHY_REQUEST_ERR:DOM例外3" - 错误?.

基本上,你必须添加

dataType: 'html'
Run Code Online (Sandbox Code Playgroud)

到$ .ajax请求.

  • @BinaryNights - 我们是否应该总是将'dataType:'html'`添加到我们的ajax请求中,以防万一? (3认同)

Bri*_*sio 51

编辑:这个答案是陈旧的,过时的.我会删除它,但这是"接受"的答案.我会注意我的意见.

我不会主张这样做了.相反,我会将所有模板分成单独的HTML文件.有人建议异步加载这些(Require.js或排序的模板缓存).这适用于小型项目,但是对于包含大量模板的大型项目,您发现自己在页面加载时会产生大量的小异步请求,这是我真的不喜欢的.(呃......好吧,你可以通过使用r.js预编译初始依赖项来解决Require.js问题,但是对于模板,这对我来说仍然是错误的)

我喜欢使用grunt任务(grunt-contrib-jst)将所有HTML模板编译成单个templates.js文件并包含它.你可以获得所有世界中最好的IMO ...模板存在于一个文件中,所述模板的编译发生在构建时(不是运行时),并且当页面启动时你没有一百个微小的异步请求.

下面的一切都是垃圾

对我来说,我更喜欢将JS文件包含在我的模板中.所以,我可能会创建一个名为view_template.js的文件,其中包含模板作为变量:

app.templates.view = " \
    <h3>something code</h3> \
";
Run Code Online (Sandbox Code Playgroud)

然后,就像包含脚本文件一样简单,然后在您的视图中使用它:

template: _.template(app.templates.view)
Run Code Online (Sandbox Code Playgroud)

更进一步,我实际上使用coffeescript,所以我的代码实际上看起来更像这样,并避免行尾转义字符:

app.templates.view = '''
    <h3>something code</h3>
'''
Run Code Online (Sandbox Code Playgroud)

使用这种方法可以避免在不需要的情况下使用require.js.

  • 这种方法会丢失任何语法突出显示,重新格式化和重构功能可用于ide.不投票. (46认同)
  • @TommiForsström我同意.我已经摆脱了这种方法.哇!2011年12月4日是很久以前在Backbone.js开发的世界:) (3认同)

Dmi*_*riy 18

这个mixin允许您以非常简单的方式使用Underscore渲染外部模板:_.templateFromUrl(url, [data], [settings]).方法API与Underscore _.template()几乎相同.包括缓存.

_.mixin({templateFromUrl: function (url, data, settings) {
    var templateHtml = "";
    this.cache = this.cache || {};

    if (this.cache[url]) {
        templateHtml = this.cache[url];
    } else {
        $.ajax({
            url: url,
            method: "GET",
            async: false,
            success: function(data) {
                templateHtml = data;
            }
        });

        this.cache[url] = templateHtml;
    }

    return _.template(templateHtml, data, settings);
}});
Run Code Online (Sandbox Code Playgroud)

用法:

var someHtml = _.templateFromUrl("http://example.com/template.html", {"var": "value"});
Run Code Online (Sandbox Code Playgroud)

  • 非常漂亮的小混合那里非常整洁!:)欢呼分享 (2认同)

Tyt*_*yth 17

我不想将require.js用于这个简单的任务,所以我使用了修改过的koorchik解决方案.

function require_template(templateName, cb) {
    var template = $('#template_' + templateName);
    if (template.length === 0) {
        var tmpl_dir = './templates';
        var tmpl_url = tmpl_dir + '/' + templateName + '.tmpl';
        var tmpl_string = '';

        $.ajax({
            url: tmpl_url,
            method: 'GET',
            contentType: 'text',
            complete: function (data, text) {
                tmpl_string = data.responseText;
                $('head').append('<script id="template_' + templateName + '" type="text/template">' + tmpl_string + '<\/script>');
                if (typeof cb === 'function')
                    cb('tmpl_added');
            }
        });
    } else {
        callback('tmpl_already_exists');
    }
}

require_template('a', function(resp) {
    if (resp == 'tmpl_added' || 'tmpl_already_exists') {
        // init your template 'a' rendering
    }
});
require_template('b', function(resp) {
    if (resp == 'tmpl_added' || 'tmpl_already_exists') {
        // init your template 'b' rendering
    }
});
Run Code Online (Sandbox Code Playgroud)

为什么要将模板附加到文档,而不是将它们存储在javascript对象中?因为在生产版本中我想生成包含所有模板的html文件,所以我不需要进行任何额外的ajax请求.同时,我不需要在我的代码中进行任何重构,就像我使用的那样

this.template = _.template($('#template_name').html());
Run Code Online (Sandbox Code Playgroud)

在我的Backbone视图中.


Man*_*ans 16

这可能略显偏离主题,但你可以使用Grunt(http://gruntjs.com/) - 它运行在node.js(http://nodejs.org/,可用于所有主要平台)上运行任务命令行.这个工具有很多插件,比如模板编译器,https://npmjs.org/package/grunt-contrib-jst.请参阅GitHub上的文档,https://github.com/gruntjs/grunt-contrib-jst.(您还需要了解如何运行节点包管理器,https://npmjs.org/.不要担心,它非常容易且功能多样.)

然后,您可以将所有模板保存在单独的html文件中,运行该工具以使用下划线预编译它们(我认为这是JST插件的依赖项,但不要担心,节点包管理器将自动为您安装依赖项).

例如,这会将您的所有模板编译为一个脚本

templates.js
Run Code Online (Sandbox Code Playgroud)

加载脚本将默认设置一个全局 - "JST" - 这是一个函数数组,可以这样访问:

JST['templates/listView.html']()

这将类似于

_.template( $('#selector-to-your-script-template'))
Run Code Online (Sandbox Code Playgroud)

如果您将该脚本标记的内容放在(templates /)listView.html中

然而,真正的踢球者是这样的:Grunt带有这个名为'watch'的任务,它基本上会监视你在本地grunt.js文件中定义的文件的变化(这基本上是你的Grunt项目的配置文件,在javascript中).如果你有咕噜声为你开始这个任务,输入:

grunt watch
Run Code Online (Sandbox Code Playgroud)

从命令行,Grunt将监视您对文件所做的所有更改,并自动执行您在grunt.js文件中为其设置的所有任务(如果它检测到更改) - 如上所述的jst任务.编辑然后保存您的文件,并将所有模板重新编译为一个js文件,即使它们分布在多个目录和子目录中.

可以配置类似的任务来linting你的javascript,运行测试,连接和缩小/ uglifying你的脚本文件.所有这些都可以与监视任务相关联,因此对文件的更改将自动触发项目的新"构建".

设置和理解如何配置grunt.js文件需要一些时间,但它非常值得花时间投入,而且我认为你不会再回到前咕噜咕噜的工作方式


nay*_*aab 15

我想可能会对你有所帮助.解决方案中的所有内容都围绕require.js库,这是一个JavaScript文件和模块加载器.

上面链接中的教程很好地展示了如何组织骨干项目.一个简单的实现也被提供.希望这可以帮助.

  • 感谢您对我的网站的参考,对于任何人来说,我已经开始了一个项目,试图实施最佳实践http://backboneboilerplate.com (3认同)