【问题标题】:Using pre-compiled templates with Handlebars.js (jQuery Mobile environment)将预编译模板与 Handlebars.js 一起使用(jQuery Mobile 环境)
【发布时间】:2012-01-29 09:28:42
【问题描述】:

我在 Handlebars 中预编译模板时有些吃力。我的 jQuery Mobile 项目在模板方面变得相当大,我希望预编译我使用的模板。

但是,我似乎找不到关于如何使用 Handlebars 进行此操作的良好解释(如分步教程)。

我仍然使用脚本标签将我的模板全部内联。我使用 NPM 安装了车把。但现在我有点迷失在如何进行。

我猜是在做类似的事情

handlebars -s event.handlebars > event.compiled

并以某种方式包括 event.compiled 内容?但是,如何称呼它。

我这样称呼我的模板

var source = $('#tmpl_profile').html(),
template = Handlebars.compile(source),
context = user.profile()),
html    = template(context);

希望有人能帮我解释一下。

【问题讨论】:

    标签: javascript jquery-mobile handlebars.js


    【解决方案1】:

    所以经过多次尝试和错误(这是学习它的最佳方式),这就是适合我的方式。

    首先-将所有模板外部化,假设您在脚本标签中有一个模板,例如

    <script id="tmpl_ownevents" type="text/templates">
        {{#unless event}}
            <div class="notfoundevents"><p>No events for you</p></div>    
        {{/unless}}
    </script>
    

    创建一个名为 events.tmpl 的新文件并将模板复制/粘贴到该文件中。 一定要自己删除脚本元素,这个陷阱让我有点......

    像这样安装 Handlebars 命令行脚本

    npm install -g handlebars
    

    转到您保存 events.tmpl 的文件夹并运行

    handlebars events.tmpl -f events.tmpl.js
    

    在您包含 Handlebars.js 后将编译后的 javascript 包含到您的 HTML 中

    <script src="events.tmpl.js"></script>
    

    现在剩下的就是将您的正常模板代码更改为类似于以下内容的内容

    var template = Handlebars.templates['events.tmpl'], // your template minus the .js
        context = events.all(), // your data
        html    = template(context);
    

    你有它,超快速的预编译 Handlebars 模板。

    【讨论】:

    • 语义上,我发现最好不要给模板文件“js”扩展名,因为这些文件不是“纯”javascript文件。 handlebars 编译器理解“handlebars”扩展名并将其从最终模板名称中删除,因此对于 events.handlebars 而不是 Handlebars.templates['events.tmpl'];你得到 Handlebars.templates['events'];我觉得更干净一些。
    • 对于那些使用 RequireJS 的人,handlebars 命令行实用程序中有一个选项(-a--amd),它告诉它创建一个 AMD 样式的函数,您以后可以使用 RequireJS 加载该函数。
    • @PeterPajchl 您的回答有点令人困惑,从表面上看对我不起作用,所以我想为其他人澄清一下。是的,将模板文件命名为“name.handlebars”在编译之前,并选择将其输出到“name.js”(然后在您的 html 文件中引用)将导致 Handlebars.templates ['姓名']。但是,这并不意味着您应该将文件输出到“name.handlebars”并在html中引用它。
    • 您是否必须为多个模板提供多个文件?有人可以解释一下您将如何外部化 10 多个模板吗?理想情况下,它们都在一个文件中,通过删除脚本标签,您已经删除了特定模板可能具有的唯一标识。
    • @xckpd7 你不需要外化模板,见fiddle;因此您可以编译任意数量的把手并将它们连接到单个文件,编译时间名称将决定 Handlebars.templates 属性
    【解决方案2】:

    另一个很好的选择是使用GruntJS。安装后:

    npm install grunt-contrib-handlebars --save-dev

    然后在你的 gruntfile.js 中

    grunt.initConfig({
        dirs: {
          handlebars: 'app/handlebars'
        },
        watch: {
          handlebars: {
            files: ['<%= handlebars.compile.src %>'],
            tasks: ['handlebars:compile']
          }
        },
        handlebars: {
          compile: {
            src: '<%= dirs.handlebars %>/*.handlebars',
            dest: '<%= dirs.handlebars %>/handlebars-templates.js'
          }
        }
    });
    
    
    grunt.loadNpmTasks('grunt-contrib-handlebars');
    

    然后,您只需在控制台中输入grunt watch,grunt 就会自动将所有 *.handlebars 文件编译到您的 handlebars-templates.js 文件中。

    使用车把的方式非常棒。

    【讨论】:

      【解决方案3】:

      这是我的做法:

      准备

      我们将假设您所有的模板变量都在一个名为 context 的变量中:

      var context = {
          name: "Test Person",
          ...
      };
      

      模板的放置位置

      创建一个包含所有模板的目录(我们称之为templates/) 在此处添加您的模板,称为 filename.handlebars

      你的目录结构:

      .
      └── templates
          ├── another_template.handlebars
          └── my_template.handelbars
      

      编译模板

      首先进入你的根目录,然后使用 npm CLI 程序编译你的模板:

      handlebars templates/*.handlebars -f compiled.js

      新目录结构:

      .
      ├── compiled.js
      └── templates
          ├── another_template.handlebars
          └── my_template.handlebars
      

      用法

      在包含运行时后,在 HTML 页面中包含 compiled.js

      <script src="handlebars.runtime.js"></script>
      <script src="compiled.js"></script>
      

      使用全局 Handlebars 对象呈现您的模板:

      // If you used JavaScript object property conform file names
      // Original filename: "my_template.handlebars"
      Handlebars.templates.my_template(context)
      
      // if you used special characters which are not allowed in JavaScript properties
      // Original filename: "my-template.handlebars"
      Handlebars.templates["my-template"](context)
      

      备注

      注意文件扩展名.handlebars。编译模板时会自动剥离。

      额外:如果您将其中一个 Jetbrains IDE 与 Handlebars/Mustache plugin 一起使用,您甚至可以获得相当不错的编辑器支持。

      【讨论】:

      • 我正在考虑使用这种方法来加载我的预编译模板,但我想在开始实现它之前知道一件事。是否可以通过require.js同时加载handlebars.runtimecompiled.js? ..
      • 我对requirejs没有深入的了解,但是你应该将handlebars.runtime定义为compiled.js的依赖(并且你的脚本有compiled.js作为依赖)。您可以手动执行此操作(通过在定义中手动包装已编译的代码)或查找为您执行此操作的现有库。
      • @apfelbox 什么是 npm CLI 以及如何将它添加到 VS 2015?
      【解决方案4】:

      使用 Grunt 预编译 Handlebars 模板

      假设您安装了 Node.js。如果你不这样做,那就去做吧。

      1) 设置Node依赖:

      在您的应用程序根目录中添加一个名为package.json 的文件。将以下内容粘贴到该文件中:

      {
        "devDependencies": {
         "grunt-contrib-handlebars": "~0.6.0",
          "grunt-contrib-watch": "~0.5.3",
          "handlebars": "~1.3.0"
        },
      }
      

      这个 JSON 文件告诉 Node 它需要安装哪些包。正如您将在下一步中看到的那样,这有助于让其他开发人员快速启动并运行。

      2) 安装节点依赖:

      在您的终端/命令提示符/powershell 中,cd 进入您的项目根目录并运行以下命令:

      npm install grunt -g
      npm install grunt-cli -g
      

      并安装 package.json 中列出的依赖项:

      npm install
      

      现在您已经安装了所有需要的节点依赖项。在您的项目根目录中,您会看到一个node_modules folder

      3) 配置 Grunt:

      在您的项目根目录中,创建一个名为Gruntfile.js 的文件。将以下内容粘贴到该文件中:

      module.exports = function(grunt) {
      
          var TEMPLATES_LOCATION        = "./src/templates/",       // don't forget the trailing /
              TEMPLATES_EXTENSION       = ".hbs",
              TEMPLATES_OUTPUT_LOCATION = TEMPLATES_LOCATION,       // don't forget the trailing /
              TEMPLATES_OUTPUT_FILENAME = "compiled_templates.js";  // don't forget the .js
      
          grunt.initConfig({
              watch: {
                  handlebars: {
                      files: [TEMPLATES_LOCATION + '**/*' + TEMPLATES_EXTENSION],
                      tasks: ['handlebars:compile']
                  }
              },
              handlebars: {
                  compile: {
                      src: TEMPLATES_LOCATION + '**/*' + TEMPLATES_EXTENSION,
                      dest: TEMPLATES_OUTPUT_LOCATION + TEMPLATES_OUTPUT_FILENAME,
                      options: {
                          amd: true,
                          namespace: "templates"
                      }
                  }
              }
          });
      
          grunt.loadNpmTasks('grunt-contrib-handlebars');
          grunt.loadNpmTasks('grunt-contrib-watch');
      
      }
      

      4) 根据自己的喜好进行配置:

      如果您不使用 Require.js,您需要将 handlebars.compile.options.amd 更改为 false。您可能还想根据自己的喜好调整namespace 选项。如果您使用的是 require/amd 模块,则命名空间属性并不重要(如果您将其删除,则默认为“JST”)。

      因为所有项目结构都有些不同,所以您只需稍微配置一下 Gruntfile。修改常量TEMPLATES_LOCATIONTEMPLATES_EXTENSIONTEMPLATES_OUTPUT_LOCATIONTEMPLATES_OUTPUT_FILENAME 以适合您的项目。

      如果您的模板分散在整个应用程序中,您需要将TEMPLATES_LOCATION 更改为可能的最低目录。确保您的模板与您的 node_modules、bower_components 或任何其他 3rd 方目录隔离,因为您不希望 Grunt 将 3rd 方模板编译到您的应用程序编译的模板中。如果您将自己的所有代码都包含在 ./src./js./app 目录中,就可以了。

      5) 使用 Grunt 编译模板:

      要在后台运行 grunt,打开你的终端并 cd 进入你的项目根目录并运行命令:grunt watch:handlebarsgrunt watch 也可以)。随着 grunt 在后台运行,对模板文件的所有更改都将自动编译,并且指定的输出文件 handlebars.compile.dest 将根据需要重写。输出将如下所示:

      Running "watch" task
      Waiting...
      

      要单独运行编译任务,打开你的终端和cd到你的项目根目录并运行命令:grunt handlebars:compilegrunt:handlebars也可以)。输出将类似于:

      Running "handlebars:compile" <handlebars> task
      File "./src/templates/compiled_templates.js" created.
      
      Done, without errors.
      

      【讨论】:

        【解决方案5】:

        Handlebars 2.0.0 alpha 更新:

        @Macro 已经非常清楚地解释了它如何与 1 个模板一起工作,请参阅this answer for how to make handlebars.js works

        如果您在使用预编译模板时看到“TypeError: 'undefined' is not a function”:

        在评估 templateSpec.call(container, Handlebars, context, options.helpers, options.partials, options.data) 时,此错误发生在“handlebar.runtime.js”第 436 行,

        因为安装的编译器 npm 与浏览器使用的不匹配。下载的最新稳定版是v1.3.0,如果你使用npm install handlebars,它会为你安装2.0.0-alpha4。

        请查看

        handlebars any_your_template_before_compile.handlebars | grep "compiler"
        

        如果您确实安装了车把 2.0.0-alpha4,您会喜欢的:

        this.compiler = [5, '>=2.0.0']
        

        第一个数字代表车把编译器的版本。在浏览器控制台中输入以下代码,查看结果是否与版本匹配。

        Handlebars.COMPILER_REVISION
        

        如果你的浏览器版本为 4 的编译器 5,那么你就会遇到上述问题。

        要修复它,请使用以下命令安装车把 1.3.0

        npm install handlebars@1.3.0 -g
        

        然后尝试再次编译它,你会看到这一次,它会为你提供匹配的版本信息,你可以使用预编译的模板。

        this.compilerInfo = [4, '>=1.0.0']
        


        如果您有大量模板,请解释一下:

        首先将你的支撑模板的每个部分外部化:event.handlebars、item.handlebars 等...你可以将它们全部放在一个文件夹中,比如“/templates”

        编译所有文件并使用以下命令将其连接成1个文件:

        handlebars *.handlebars -f templates.js
        

        并在你的 HTML 中包含 handlebars.runtime,这个文件

        <script src="/lib/handlebars.runtime.js"></script>
        <script src="templates.js"></script>
        

        模板将按其名称注入到 Handlebars.templates 中。例如,event.handlebars 可以通过 Handlebars.tempaltes['event'] 访问。

        【讨论】:

        • 使用 v2.0.0-alpha.4 我必须调用 Handlebars.template(Handlebars.templates.MYTEMPLATE)(CONTEXT) 才能使用我的预编译模板。看起来并不那么优雅,所以要么我错过了一些东西,要么它只是 alpha。不管怎样,很高兴我想通了。
        猜你喜欢
        • 2013-03-31
        • 1970-01-01
        • 2012-08-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-06-03
        相关资源
        最近更新 更多