• Express模版引擎hbs备忘


    最近几天折腾了下express,想找个合适的模版引擎,下面是一些折腾过程的备忘

    选择标准

    选择一门模版语言时,可能会考虑的几点

    • 语法友好(micro tmpl那种语法真是够了)
    • 支持模版嵌套(子模版的概念)
    • 支持模版继承(extend)
    • 前后端共用
    • 有容错处理(最好定位到具体出错位置)
    • 支持预编译(性能好)

    注意到hbs,似乎满足大部分的需求:https://github.com/donpark/hbs

    getting started

    demo地址:https://github.com/chyingp/blog/tree/master/demo/2015.04.01-hbs/getting-started 
    目录结构如下:

    .
    ├── app.js
    ├── node_modules
    │   ├── express
    │   └── hbs
    ├── package.json
    └── views
        └── index.hbs

    看下app.js内容,还是比较容易理解的。模版views/index.hbs没什么好说的,语法跟handlbars一样

    var express = require('express'),
        hbs = require('hbs'),
        app = express();
    
    app.set('view engine', 'hbs');  // 用hbs作为模版引擎
    app.set('views', __dirname + '/views'); // 模版所在路径
    
    app.get('/', function(req, res){
        res.render('index', {title: 'hbs demo', author: 'chyingp'});
    });
    
    app.listen(3000);   

    模版继承:layout.hbs

    demo地址:https://github.com/chyingp/blog/tree/master/demo/2015.04.01-hbs/inherit-from-layout

    如果稍微看过hbs源码可以知道,hbs默认会到views下找layout.hbs这个模版,将这个模板作为基本骨架,来渲染返回的页面。

    getting-started里的例子来说,比如用户请求 http://127.0.0.1:3000,那么,处理步骤如下

    1. 查找views/index.hbs,进行编译,并将编译的结果保存为 A
    2. 查找views/layout.hbs,如果 
      1. 存在:对layout.hbs进行编译,其中{{{body}}}标签替换成 A,并返回最终编译结果B
      2. 不存在:返回A

    直接看例子。目录机构如下,可以看到多了个layout.hbs

    .
    ├── app.js
    ├── node_modules
    │   ├── express
    │   └── hbs
    ├── package.json
    ├── public
    │   └── style.css
    └── views
        ├── index.hbs
        ├── layout.hbs
        └── profile.hbs

    layout.hbs的内容如下:

    <!DOCTYPE html>
    <html>
    <head>
        <title>{{title}}</title>
        <link rel="stylesheet" type="text/css" href="/style.css">
    </head>
    <body>
    
    {{{body}}}
    
    </body>
    </html>

    相应的,index.hbs调整为

    <h1>Demo by {{author}}</h1>
    
    <p>{{author}}: welcome to homepage, I'm handsome!</p>

    再次访问 http://127.0.0.1:3000,可以看到返回的页面

    Alt text

    模版继承+自定义扩展

    demo地址:https://github.com/chyingp/blog/tree/master/demo/2015.04.01-hbs/inherit-and-override

    在项目中,我们会有这样的需求。页面的基础骨架是共享的,但某些信息,每个页面可能是不同的,比如引用的css文件、meta标签等。那么,除了上面提到的“继承”之外,还需要引入类似“覆盖”的特性。

    hbs官方其实就提供了demohttps://github.com/donpark/hbs/blob/master/examples/extend/ ,感兴趣的同学可以去围观下。可以看到,在app.js里面加入了下面的 helper function`,这就是实现”覆盖“ 的关键代码了。

    var blocks = {};
    
    hbs.registerHelper('extend', function(name, context) {
        var block = blocks[name];
        if (!block) {
            block = blocks[name] = [];
        }
    
        block.push(context.fn(this)); // for older versions of handlebars, use block.push(context(this));
    });
    
    hbs.registerHelper('block', function(name) {
        var val = (blocks[name] || []).join('
    ');
    
        // clear the block
        blocks[name] = [];
        return val;
    });

    此外,layout.hbs需要做点小改动。里面比较明显的变化是加入了下面的block标记

    {{{block "stylesheets"}}}
     {{{block "scripts"}}}

    那么,可以在index.hbs里对这些标记的内容进行覆盖(或者说自定义),包括其他的模版,如果有需要,都可以对这两个`block进行覆盖。

    {{#extend "stylesheets"}}
    <link rel="stylesheet" href="/css/index.css"/>
    {{/extend}}
    
    let the magic begin
    
    {{#extend "scripts"}}
    <script>
      document.write('foo bar!');
    </script>
    {{/extend}}

    那么问题来了。如果有这样的需求:所有的页面,都引用 style.css,只有 index.hbs 引用 index.css,那么上面的改动还不足以满足这个需求。

    其实,只需要改几行代码就可以实现了,扩展性点个赞。改动后的app.js如下

    var blocks = {};
    
    hbs.registerHelper('extend', function(name, context) {
        var block = blocks[name];
        if (!block) {
            block = blocks[name] = [];
        }
    
        block.push(context.fn(this)); // for older versions of handlebars, use block.push(context(this));
    });
    
    // 改动主要在这个方法
    hbs.registerHelper('block', function(name, context) {
        var len = (blocks[name] || []).length;
        var val = (blocks[name] || []).join('
    ');
    
        // clear the block
        blocks[name] = [];
    
        return len ? val : context.fn(this);
    });
     
     
     
     
  • 相关阅读:
    PAT Basic 1077 互评成绩计算 (20 分)
    PAT Basic 1055 集体照 (25 分)
    PAT Basic 1059 C语言竞赛 (20 分)
    PAT Basic 1072 开学寄语 (20 分)
    PAT Basic 1049 数列的片段和 (20 分)
    蓝桥杯BASIC-13 数列排序
    蓝桥杯入门——3.序列求和
    蓝桥杯入门——2.圆的面积
    蓝桥杯入门——1.Fibonacci数列
    树的总结(遍历,BST,AVL原型,堆,练习题)
  • 原文地址:https://www.cnblogs.com/chyingp/p/hbs-getting-started.html
Copyright © 2020-2023  润新知