zoukankan      html  css  js  c++  java
  • 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);
    });
     
     
     
     
  • 相关阅读:
    [BZOJ2729]排队
    [BZOJ2839]集合计数
    [BZOJ2111] Perm 排列计数
    Unet 项目部分代码学习
    数据增强代码
    论文阅读笔记五:U-Net: Convolutional Networks for Biomedical Image Segmentation(CVPR2015)
    CTPN项目部分代码学习
    论文阅读笔记四:CTPN: Detecting Text in Natural Image with Connectionist Text Proposal Network(ECCV2016)
    R2CNN项目部分代码学习
    VOC数据集生成代码使用说明
  • 原文地址:https://www.cnblogs.com/chyingp/p/hbs-getting-started.html
Copyright © 2011-2022 走看看