Clark To Do The blog of Clark

Handlebars.js

1.介绍

Handlebars.js 是 JavaScript 一个语义模板库, 通过对view和data的分离来快速构建Web模板. 它采用”Logic-less template”(无逻辑模版)的思路, 在加载时被预编译, 而不是到了客户端执行到代码时再去编译, 这样可以保证模板加载和运行的速度. Handlebars.js兼容Mustache, 你可以在Handlebars.js中导入Mustache模板.

2.安装

Handlebars.js的安装十分简单, 只要从Github下载最新版本:https://github.com/wycats/Handlebars.js或通过访问官网获取:http://Handlebars.js.com. 目前Handlebars.js已经被许多项目广泛使用了, Handlebars.js是一个纯JS库, 因此你可以像使用其他JS脚本一样用script标签来包含Handlebars.js.

3.为什么选择Handlebars.js

  • Handlebars.js是目前最高级的(预编译类型), 功能丰富并且流行的JavaScript模板引擎.
  • Handlebars.js是一个无逻辑模板引擎, 意味着在你的HTML模板中是没有任何逻辑的.
  • Handlebars.js以及其他任何模板引擎最重要的特性就是保证HTML页面的简单与纯净并且与JavaScript中的业务逻辑解耦, Handlebars.js在这方面做的很好. 事实上, Dust.js也是一个无逻辑模板引擎, 同时是Handlebars.js的优秀的备选方案.
  • 虽然Backbone.js通过Underscore.js的模板引擎进行包装, 但是在Backbone.js内使用Handlebars.js非常简便.
  • 它有着相当详细的文档, 以及活跃的开源社区支持.

4.基本语法与简单使用

  • Handlebars expressions 是handlebars模板中最基本的单元, 使用方法是加两个花括号{{value}}, handlebars模板会自动匹配相应的数值, 对象, 甚至是函数.
  • handlebars会根据上下文来自动对表达式进行匹配, 如果匹配项是个变量, 则会输出变量的值, 如果匹配项是个函数, 则函数会被调用.
  • 如果没找到匹配项, 则没有输出. 表达式也支持点操作符, 因此你可以使用{{content.title}}这样的形式来调用嵌套的值或者方法, handlebars会根据当前上下文输出content变量的title属性的值.
  • 在JavaScript中, 使用Handlebars.compile()方法来编译模板.
<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>Handlebars Demo 2</title>
    <script type="text/javascript" src="js/jquery-1.11.1.js"></script>
    <script type="text/javascript" src="js/handlebars-v2.0.0.js"></script>
    <script type="text/javascript">
    $(document).ready(function(){
        //用jquery获取模板
        var source = $("#tpl").html();
        //预编译模板
        var template = Handlebars.compile(source);
        //模拟json数据
        var context = { name: "Handlebars", content: "This is the Handlebars.js demo 2"};
        //匹配json内容
        var html = template(context);
        //输入模板
        $("body").html(html);
        });
    </script>
</head>
<body>
    <script id="tpl" type="text/x-handlebars-template">
        <div class="demo">
            <h1>{{name}}</h1>
            <p>{{content}}</p>
        </div>
    </script>
</body>
</html>

5.路径与注释

  • 简单路径: <p>{{name}}</p>
  • 嵌套路径: <p>{{.name}}</p>
  • 父路径: {{../name}}
  • 相对路径: {{./name}} or {{this/name}} or {{this.name}}
  • 注释: {{!– –}} or {{! }} (不会展现在输出的HTML内, 如果有此需求, 可用HTML注释)

6.Block表达式

  • 当需要对某条表达式进行复杂操作时,则可以使用Blocks.
  • 在Handlebars中, 可以在表达式后面跟随一个#号来表示Blocks,然后通过{{/表达式}}来结束Blocks. 如果当前的表达式是一个数组,则Handlebars会“自动展开数组”,并将Blocks的上下文设为数组中的元素.
<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>Handlebars Demo 3</title>
    <script type="text/javascript" src="js/jquery-1.11.1.js"></script>
    <script type="text/javascript" src="js/handlebars-v2.0.0.js"></script>
    <script type="text/javascript">
    $(document).ready(function(){
        //用jquery获取模板
        var source = $("#tpl").html();
        //预编译模板
        var template = Handlebars.compile(source);
        //模拟json数据
        var context = {
            tools: [
            {lib: "Backbone"},
            {lib: "JQuery"},
            {lib: "Handlebars"}
            ]
        };
        //匹配json内容
        var html = template(context);
        //输入模板
        $("body").html(html);
        });
    </script>
</head>
<body>
    <script id="tpl" type="text/x-handlebars-template">
        <ul>
            {{#tools}}
            <li>{{lib}}</li>
            {{/tools}}
        </ul>
    </script>
</body>
</html>

6.Block helper

  • Block helper是handlebars内置的块表达式, 较为常用的有如下表达式:
  • each - 用于遍历列表内容, 通过this引用遍历的元素
  • if else - 指定渲染dom节点的条件, 如果返回false,undefined, null, “” 或者 [] (a “falsy” value), 则不渲染块内的dom节点.
  • unless - 反向的if语法
  • with - 转移模板数据上下文环境(复杂的模板内很有帮助)

7.自定义helper

Handlebars可以从任何上下文访问一个模板,你可以使用Handlebars.registerHelper()方法来注册一个helper.

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title>Handlebars Demo 4</title>
    <script type="text/javascript" src="js/jquery-1.11.1.js"></script>
    <script type="text/javascript" src="js/underscore.js"></script>
    <script type="text/javascript" src="js/backbone.js"></script>
    <script type="text/javascript" src="js/handlebars-v2.0.0.js"></script>
    <script type="text/javascript">

    $(document).ready(function(){

        Handlebars.registerHelper('agree_button', function() {
            var emotion = Handlebars.escapeExpression(this.emotion),
            name = Handlebars.escapeExpression(this.name);

            return new Handlebars.SafeString(
                "<button>I agree. I " + emotion + " " + name + "</button>"
            );
        });

        //用jquery获取模板
        var source = $("#tpl").html();
        //预编译模板
        var template = Handlebars.compile(source);
        //模拟json数据
        var context = {
            items: [
            {name: "Handlebars", emotion: "love"},
            {name: "Mustache", emotion: "enjoy"},
            {name: "Ember", emotion: "want to learn"}
            ]
        };
        //匹配json内容
        var html = template(context);
        //输入模板
        $("body").html(html);
    });
    </script>
</head>
<body>
    <script type="text/template" id="tpl">
        <ul>
            {{#each items}}
            <li>{{agree_button}}</li>
            {{/each}}
        </ul>
    </script>
</body>
</html>

8.注释

Handlebars的注释写法: {{! handlebars comments }}.

9.路径访问

  • Handlebar支持路径访问, 甚至嵌套路径,使得模板中可以查找嵌套低于当前上下文的属性
  • 可以通过”.”来访问属性也可以使用”../”来访问父级属性. 例如:(使用.访问的例子)

10.预编译

  • 安装node.js: http://nodejs.org/download/
  • 安装Handlebars.js的预编译器 : npm -g install handlebars
  • 预编译模板:
  • handlebars -m ./templates/Handlebars.hbs > ./templates/templates.js
  • JS中获取模板的传统方式:
  • var source = $(“#myTemsplate”).html();
  • var template = Handlebars.compile(source);
  • 改为直接获取: var template = Handlebars.templates[‘myTemplate’];

11.调试

把下面一段”debug helper”加载到你的JavaScript代码里,然后在模板文件里通过{{debug}}或是{{debug someValue}}方便调试数据

Handlebars.registerHelper("debug", function(optionalValue) {
    console.log("Current Context");
    console.log("====================");
    console.log(this);
    if (optionalValue) {
        console.log("Value");
        console.log("====================");
        console.log(optionalValue);
    }
});
comments powered by Disqus