Javascript 下划线中的外部模板

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8366733/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 05:42:24  来源:igfitidea点击:

External template in Underscore

javascriptbackbone.jsunderscore.js

提问by Tomá?

I use Underscore template. It is possible to attach a external file as template?

我使用下划线模板。可以附加外部文件作为模板吗?

In Backbone View I have:

在主干视图中,我有:

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

 initialize: function(){                                            
  this.words = new WordList;            
  this.index = 0;
  this.render();
 },

In my html is:

在我的 html 中是:

<script id="practice-text-template" type="text/template">
   <h3>something code</h3>
</script>

It works well. But I need external template. I try:

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

<script id="practice-text-template" type="text/template" src="templates/tmp.js">

or

或者

textTemplate: _.template( $('#practice-text-template').load('templates/tmp.js') ),

or

或者

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

but it did not work.

但它没有用。

采纳答案by Brian Genisio

EDIT: This answer is old and outdated. I'd delete it, but it is the "accepted" answer. I'll inject my opinion instead.

编辑:这个答案是旧的和过时的。我会删除它,但它是“已接受”的答案。我来发表一下我的看法。

I wouldn't advocate doing this anymore. Instead, I would separate all templates into individual HTML files. Some would suggest loading these asynchronously (Require.js or a template cache of sorts). That works well on small projects but on large projects with lots of templates, you find yourself making a ton of small async requests on page load which I really dislike. (ugh... ok, you can get around it with Require.js by pre-compiling your initial dependencies with r.js, but for templates, this still feels wrong to me)

我不会再提倡这样做了。相反,我会将所有模板分成单独的 HTML 文件。有些人会建议异步加载这些(Require.js 或各种模板缓存)。这在小型项目上效果很好,但在包含大量模板的大型项目中,您会发现自己在页面加载时发出了大量我非常不喜欢的小型异步请求。(呃……好吧,你可以用 Require.js 通过用 r.js 预编译你的初始依赖来解决它,但对于模板,这对我来说仍然是错误的)

I like using a grunt task (grunt-contrib-jst) to compile all of the HTML templates into a single templates.js file and include that. You get the best of all worlds IMO... templates live in a file, compilation of said templates happen at build time (not runtime), and you don't have one hundred tiny async requests when the page starts up.

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

Everything below is junk

下面的都是垃圾

For me, I prefer the simplicity of including a JS file with my template. So, I might create a file called view_template.js which includes the template as a variable:

对我来说,我更喜欢在我的模板中包含一个 JS 文件的简单性。因此,我可能会创建一个名为 view_template.js 的文件,其中包含模板作为变量:

app.templates.view = " \
    <h3>something code</h3> \
";

Then, it is as simple as including the script file like a normal one and then using it in your view:

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

template: _.template(app.templates.view)

Taking it a step further, I actuallyuse coffeescript, so my code actually looks more like this and avoid the end-of-line escape characters:

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

app.templates.view = '''
    <h3>something code</h3>
'''

Using this approach avoids brining in require.js where it really isn't necessary.

使用这种方法可以避免在真正不需要的地方引入 require.js。

回答by koorchik

Here is a simple solution:

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

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

Using "async: false" here is not a bad way because in any case you must wait until template will be loaded.

在这里使用 "async: false" 并不是一个坏方法,因为在任何情况下你都必须等到模板被加载。

So, "render" function

所以,“渲染”功能

  1. allows you to store each template in separate html file in static dir
  2. is very lightweight
  3. compiles and caches templates
  4. abstracts template loading logic. For example, in future you can use preloaded and precompiled templates.
  5. is easy to use
  1. 允许您将每个模板存储在静态目录中的单独 html 文件中
  2. 非常轻巧
  3. 编译和缓存模板
  4. 抽象模板加载逻辑。例如,将来您可以使用预加载和预编译的模板。
  5. 易于使用

[I am editing the answer instead of leaving a comment because I believe this to be important.]

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

if templates are not showing up in native app, and you see HIERARCHY_REQUEST_ERROR: DOM Exception 3, look at answer by Dave Robinson to What exactly can cause an "HIERARCHY_REQUEST_ERR: DOM Exception 3"-Error?.

如果模板未显示在本机应用程序中,并且您看到了HIERARCHY_REQUEST_ERROR: DOM Exception 3,请查看 Dave Robinson 对什么会导致“HIERARCHY_REQUEST_ERR:DOM Exception 3”-错误的回答.

Basically, you must add

基本上,您必须添加

dataType: 'html'

to the $.ajax request.

到 $.ajax 请求。

回答by Dmitriy

This mixin allows you to render external template using Underscorein very simple way: _.templateFromUrl(url, [data], [settings]). Method API is almost the same as Underscore's_.template(). Caching included.

这种混入可以渲染使用外部模板下划线以非常简单的方式:_.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);
}});

Usage:

用法:

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

回答by Tyth

I didn't want to use require.js for this simple task, so I used modified koorchik's solution.

我不想将 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
    }
});

Why to append templates to document, rather than storing them in javascript object? Because in production version I would like to generate html file with all templates already included, so I won't need to make any additional ajax requests. And in the same time I won't need to make any refactoring in my code, as I use

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

this.template = _.template($('#template_name').html());

in my Backbone views.

在我的 Backbone 视图中。

回答by Mansiemans

This might be slightly off topic, but you could use Grunt (http://gruntjs.com/) - which runs on node.js (http://nodejs.org/, available for all major platforms) to run tasks from the command line. There are a bunch of plugins for this tool, like a template compiler, https://npmjs.org/package/grunt-contrib-jst. See documentation on GitHub, https://github.com/gruntjs/grunt-contrib-jst. (You will also need to understand how to run node package manager, https://npmjs.org/. Don't worry, it's incredibly easy and versatile. )

这可能有点偏离主题,但您可以使用 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/。别担心,它非常简单且用途广泛。)

You can then keep all your templates in separate html files, run the tool to precompile them all using underscore (which I believe is a dependency for the JST plugin, but don't worry, node package manager will auto install dependencies for you).

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

This compiles all your templates to one script, say

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

templates.js

Loading the script will set a global - "JST" by default - which is an array of functions, and can be accessed like so:

加载脚本将设置一个全局 - 默认情况下“JST” - 这是一个函数数组,可以像这样访问:

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

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

which would be similar to

这将类似于

_.template( $('#selector-to-your-script-template'))

if you put the content of that script tag in (templates/)listView.html

如果你把那个脚本标签的内容放在 (templates/)listView.html

However, the real kicker is this: Grunt comes with this task called 'watch', which will basically monitor changes to files that you have defined in your local grunt.js file (which is basically a config file for your Grunt project, in javascript). If you have grunt start this task for you, by typing:

然而,真正的问题在于:Grunt 附带了这个名为“watch”的任务,它基本上会监视您在本地 grunt.js 文件中定义的文件的更改(这基本上是您的 Grunt 项目的配置文件,在 javascript 中) )。如果您有 grunt 为您启动此任务,请键入:

grunt watch

from the command line, Grunt will monitor all changes you make to the files and auto-execute all tasks that you have setup for it in that grunt.js file if it detects changes - like the jsttask described above. Edit and then save your files, and all your templates recompile into one js file, even if they are spread out over a number of directories and subdirectories.

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

Similar tasks can be configured for linting your javascript, running tests, concatenating and minifying / uglifying your script files. And all can be tied to the watch task so changes to your files will automatically trigger a new 'build' of your project.

可以配置类似的任务来检查您的 javascript、运行测试、连接和缩小/丑化您的脚本文件。并且所有这些都可以与监视任务相关联,因此对文件的更改将自动触发项目的新“构建”。

It takes some time to set things up and understand how to configure the grunt.js file, but it well, well worth the time invested, and I don't think you will ever go back to a pre-grunt way of working

设置并了解如何配置 grunt.js 文件需要一些时间,但是非常值得投入时间,而且我认为您永远不会回到 grunt 之前的工作方式

回答by nayaab

I think thisis what might help you. Everything in the solution revolves around require.jslibrary which is a JavaScript file and module loader.

我想可能对你有帮助。解决方案中的一切都围绕着require.js库,它是一个 JavaScript 文件和模块加载器。

The tutorial at the link above shows very nicely how a backbone project could be organized. A sample implementationis also provided. Hope this helps.

上面链接中的教程很好地展示了如何组织主干项目。还提供了一个示例实现。希望这可以帮助。

回答by j040p3d20

I got interested on javascript templating and now I'm taking the first steps with backbone. This is what i came up with and seems to work pretty well.

我对 javascript 模板很感兴趣,现在我正在使用主干迈出第一步。这是我想出的,似乎工作得很好。

window.App = {

    get : function(url) {
        var data = "<h1> failed to load url : " + url + "</h1>";
        $.ajax({
            async: false,
            url: url,
            success: function(response) {
                data = response;
            }
        });
        return data;
    }
}

App.ChromeView = Backbone.View.extend({
    template: _.template( App.get("tpl/chrome.html") ),
    render: function () {
        $(this.el).html(this.template());
        return this;
    },
});

App.chromeView = new App.ChromeView({ el : document.body });
App.chromeView.render();

回答by user1828189

I had to set the data type to "text" to make it work for me:

我必须将数据类型设置为“文本”才能使其对我有用:

get : function(url) {
    var data = "<h1> failed to load url : " + url + "</h1>";
    $.ajax({
        async: false,
        dataType: "text",
        url: url,
        success: function(response) {
            data = response;
        }
    });
    return data;
}

回答by Kaloyan Stamatov

I found a solution that works for me with using jQuery.

我找到了一个使用 jQuery 对我有用的解决方案。

I add the underscore template code, with jQuery.load() method, to the main html file.

我使用 jQuery.load() 方法将下划线模板代码添加到主 html 文件中。

Once it's there, I'm using it for generating the templates. All need to happen synchronously!

一旦它在那里,我就用它来生成模板。一切都需要同步发生!

The concept is:

概念是:

I have a underscore map template code:

我有一个下划线地图模板代码:

<!-- MAP TEMPLATE-->
<script type="text/template" id="game-map-template">
    <% _.each(rc, function(rowItem, index){ %>
      <ul class="map-row" data-row="<%- index %>">
        <li class="map-col <%- colItem.areaType ? 'active-area' : '' %>"></li>
        ...
</script>

And I put that code in a file called map-template.html

我将该代码放在一个名为map-template.html的文件中

After that I create a a wrapper for the template files.

之后,我为模板文件创建了一个包装器。

<div id="templatesPool"></div>

Then I include that file in my main html file like so.

然后我像这样将该文件包含在我的主 html 文件中。

In head:

在头:

<!-- Template Loader -->
<script> 
    $(function(){
      $("#templatesPool").append($('<div>').load("map-template.html")); 
    });
</script> 

Cheers.

干杯。

回答by ziad-saab

I know this question is really old but it came up as the first result on a google search for underscore ajax templates.

我知道这个问题真的很老,但它是谷歌搜索下划线 ajax 模板的第一个结果。

I was tired of not finding a good solution for this so I created my own:

我厌倦了找不到一个好的解决方案,所以我创建了自己的:

https://github.com/ziad-saab/underscore-async-templates

https://github.com/ziad-saab/underscore-async-templates

In addition to loading underscore templates using AJAX, it adds <% include %> functionality. I hope it can be useful to someone.

除了使用 AJAX 加载下划线模板外,它还添加了 <% include %> 功能。我希望它对某人有用。