Javascript 把手,加载外部模板文件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26643503/
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-22 23:10:41  来源:igfitidea点击:

Handlebars, loading external template files

javascripthandlebars.jstemplate-engine

提问by CaptSaltyHyman

My goal is to put all my Handlebars templates in a single folder, as so:

我的目标是将所有 Handlebars 模板放在一个文件夹中,如下所示:

templates/products.hbs
templates/comments.hbs

I found this snippet in a few places via a cursory Google search, which apparently will load in Handlebar templates in external files, which makes much more sense than putting a bunch of templates in a single index file.

我通过粗略的谷歌搜索在几个地方找到了这个片段,它显然会加载到外部文件中的 Handlebar 模板中,这比将一堆模板放在单个索引文件中更有意义。

(function getTemplateAjax(path) {
    var source;
    var template;

    $.ajax({
        url: path, //ex. js/templates/mytemplate.handlebars
        cache: true,
        success: function(data) {
            source    = data;
            template  = Handlebars.compile(source);
            $('#target').html(template);
        }               
    });         
})()

The problem is, I don't understand this function or how to use it. Why is the whole function wrapped in parentheses and then made a function call? e.g. (function x() { ... })()I don't know what this is doing.

问题是,我不明白这个功能或如何使用它。为什么整个函数都用括号括起来,然后进行函数调用?例如,(function x() { ... })()我不知道这是在做什么。

And if I'm not mistaken, looks like $('#target')is hardcoded when it shouldn't be. Furthermore, isn't this supposed to set a datavariable somewhere so the variables referenced in the template will work?? Seems the correct function should be:

如果我没记错的话,看起来$('#target')不应该是硬编码的。此外,这不是应该在data某处设置一个变量,以便模板中引用的变量可以工作吗??似乎正确的功能应该是:

function getTemplateAjax(path, target, jsonData) {
  var source;
  var template;

  $.ajax({
    url: path, //ex. js/templates/mytemplate.handlebars
    cache: true,
    success: function(data) {
      source    = data;
      template  = Handlebars.compile(source);
      $(target).html(template(jsonData));
    }               
  });         
}

Side note: if someone could point me to a better template engine, one that actually natively supports external template files, and is better organized than Handlebars, I'd be eternally grateful.

旁注:如果有人能给我指出一个更好的模板引擎,一个实际上支持外部模板文件并且比 Handlebars 组织得更好的模板引擎,我将永远感激。

Another issue: I can't actually name my files mytemplate.hbs, because when the Ajax call happens, it sees it as a binary file and it comes through as binary. I suppose this is an issue of setting the server's mime type for .hbs to text/html or text/plain, but the issue is that this is a Grunt server and I'm not sure how to change its mime types.

另一个问题:我实际上无法命名我的文件mytemplate.hbs,因为当 Ajax 调用发生时,它会将其视为二进制文件,并且以二进制文件的形式出现。我想这是将 .hbs 的服务器的 mime 类型设置为 text/html 或 text/plain 的问题,但问题是这是一个 Grunt 服务器,我不确定如何更改它的 mime 类型。

回答by istos

The code is wrapped in an IIFE(Immediately Invoked Function Expression), which means the function is executed immediately. That's what the following means:

代码包含在IIFE立即调用函数表达式)中,这意味着函数会立即执行。这就是下面的意思:

(function x() {
  console.log('hello');
})();

You can also do:

你也可以这样做:

(function() {
  console.log('hello');
}());

IIFEs are commonly used to create a "private" scope for a bit of code so that it plays nice (doesn't conflict) with anything else.

IIFE 通常用于为一些代码创建一个“私有”范围,以便它与其他任何东西都很好(不冲突)。


The second function you provided makes more sense and perhaps the first one must have been just an example.


您提供的第二个函数更有意义,也许第一个函数肯定只是一个例子。


Handlebars allows you to precompileyour templates so you don't have to compile them at run-time. Also this way you don't have to make extra HTTP requests just to load the template(s).


Handlebars 允许您预编译模板,因此您不必在运行时编译它们。同样,这样您就不必为了加载模板而发出额外的 HTTP 请求。

For example if I have the following project structure - (note that my models, collections, and views are all within main.jsjust for this example and all my .jsfiles are in my root directory):

例如,如果我有以下项目结构 - (请注意,我的模型、集合和视图都在main.js 中,仅在此示例中,我的所有.js文件都在我的根目录中):

├── Gruntfile.js
├── handlebars-v2.0.0.js
├── index.html
├── main.js
├── package.json
└── templates
    └── todo.handlebars


My todo.handlebarslooks like so - just html with Handlebars syntax:


todo.handlebars看起来像这样 - 只是带有 Handlebars 语法的 html:

<h3>{{title}}</h3>
<p>Created by: {{author}}</p>


To precompile my template I would do the following in the command line (you have to install the handlebars precompile script first with: npm install -g handlebars):


要预编译我的模板,我将在命令行中执行以下操作(您必须首先使用 : 安装把手预编译脚本npm install -g handlebars):

> handlebars templates/todo.handlebars -f todo.tpl.js

Now my project structure looks like so:

现在我的项目结构如下所示:

├── Gruntfile.js
├── handlebars-v2.0.0.js
├── index.html
├── main.js
├── package.json
├── templates
│?? └── todo.handlebars
└── todo.tpl.js

You'll see that a todo.tpl.jsfile has been added to my root directory. I could have named it something different if I wanted to as long as the extension is a .jsbecause the file contains valid JavaScript code. Also I could have specified a different directory to output it to. Remember that the todo.tpl.jsfile is the actual template that your Backbone View will use. You write your HTML in todo.handlebarsand compile it as todo.tpl.js.

您会看到一个todo.tpl.js文件已添加到我的根目录中。如果扩展名是 a,我可以给它命名不同的名称,.js因为该文件包含有效的 JavaScript 代码。我也可以指定一个不同的目录来输出它。请记住,该todo.tpl.js文件是您的主干视图将使用的实际模板。您在其中编写 HTMLtodo.handlebars并将其编译为todo.tpl.js.


Now that I have the todo.tpl.jsfile I can use Grunt to maybe concat all my JS template files into a all_templates.jsfile or I can reference each file directly in my HTML like so:


现在我有了todo.tpl.js文件,我可以使用 Grunt 将我所有的 JS 模板文件连接到一个all_templates.js文件中,或者我可以直接在我的 HTML 中引用每个文件,如下所示:

  <script src="http://code.jquery.com/jquery-2.1.1.min.js"></script>
  <script src="http://documentcloud.github.io/underscore/underscore-min.js"></script>
  <script src="http://documentcloud.github.io/backbone/backbone-min.js"></script>
  <script src="handlebars-v2.0.0.js"></script>
  <script src="todo.tpl.js"></script> <!-- My Template for a Todo item -->
  <script src="main.js"></script>


In my Backbone View, which in my case lives inside my main.jsfile, I would get the template like so:


在我的主干视图中,在我的情况下它位于我的main.js文件中,我会得到这样的模板:

var TodoView = Backbone.View.extend({
  tagName: 'li',  
  className: 'todo-item',
  events: {

  },

  // You can grab your template function with the name you chose when
  // you precompiled it from: `Handlebars.templates`
  template: Handlebars.templates.todo,

  initialize: function(options) {
    this.listenTo(this.model, 'change', this.render);
  },

  render: function() {
    this.$el.html(this.template( this.model.toJSON() ));
    return this;
  }
});


And you're done! More info here:


你完成了!更多信息在这里:

回答by rinkesh

You can read template from External file no need to put html with script tag

您可以从外部文件中读取模板,无需将 html 与 script 标签一起放置

$.get('templates/products.hbs', function (data) {
    var template=Handlebars.compile(data);
    $(target).html(template(jsonData));
}, 'html')

回答by Mike Timmerman

I have created a simple plugin to achieve this. More information about this: https://github.com/miketimmerman/load-template

我创建了一个简单的插件来实现这一点。有关此的更多信息:https: //github.com/miketimmerman/load-template