前端模板引擎学习

@onvno 2016-07-03 15:36:59发表于 iuap-design/blog

前端模板引擎学习

之前在练手node时,用过ejs模板,当时也对比过Jade,围观了一些前人在使用上的经验,众说纷纭.

有支持ejs,从语义上前端看着更舒服,如下。

<% if(!loginStatus) { %>
<div class="hero-unit">
    <h1>歡迎來到 Microblog</h1>
    <p>Microblog 是一個基於 Node.js 的微博系统。</p>
    <p>
        <a class="btn btn-primary btn-large" href="/login">登入</a>
        <a class="btn btn-large" href="/reg">立即註冊</a>
    </p>
</div>
<% } else { %>
<form method="post" action="/post" lass="well form-inline center" style="text-align:center;">
    <input type="text" class="span8" name="post">
    <button type="submit" class="btn btn-success"><i class="icon-comment icon-white"></i>發言</button>
</form>

而Jade的支持者,更是直言:**"肯定是Jade。EJS不要说跟Jade比,就是跟传统模板技术,比如Smarty比,也很挫了,比如不支持模板继承。"**Jade的语法结构,不如让我们看看:

doctype html
html(lang="en")
  head
    title= pageTitle
    script(type='text/javascript').
      if (foo) {
         bar(1 + 5)
      }
  body
    h1 Jade - node template engine
    #container.col
      if youAreUsingJade
        p You are amazing
      else
        p Get on it!
      p.
        Jade is a terse and simple
        templating language with a
        strong focus on performance
        and powerful features.

整体来说,即便如此,Jade的2个空格从心理上是接受不了的。现在问题来了,项目有需求:利用模板引擎完成页面内容的复用和嵌套,完成上线的静态页面优化。

那么该是创新的Jade,还是ejs,答案是:都不用。至少目前从需求来看,在部分功能不需求的情况下,前端模板引擎artTemplate能帮助完成。

在介绍之前,目前浅显的认为,模板引擎有以下明显优势:

  • 代码复用
  • 页面组件化

因为目前页面是静态化,所以以自己短浅的眼光看,用真正意义上的.html更能拉近前端和这个引擎世界的距离,毕竟.ejs,.jade都有种拒人千里之外的感觉。

试试artTemplate

官方第一种方法是通过页面加载template.js文件,自定义script type="text/html"来实现。demo如下

<head>
...
<script src="./template.js"></script>
</head>

<body>
<!--待插入的内容-->
<div id = "content"></div>

<!--编写模板-->
<script id="test" type="text/html">
<h1>{{title}}</h1>
<ul>
    {{each list as value i}}
        <li>索引 {{i + 1}} :{{value}}</li>
    {{/each}}
</ul>
</script>

<!--渲染模板-->
<script>
var data = {
    title: '标签',
    list: ['文艺', '博客', '摄影', '电影', '民谣', '旅行', '吉他']
};
var html = template('test', data);
document.getElementById('content').innerHTML = html;
</script>
</body>

使用以上确实可实现渲染页面,特性和缺失如下:

  • 实现方式简单
  • 页面分离不够彻底美观
  • 页面渲染在前端执行,影响性能
  • 无法实现{{include}}

前边的一定程度上都可以忍受,但是无法实现{{include}}模板嵌套就没法忍了。

于是有了第二种方法:

针对artTemplate的预编译工具:TmodJS

TmodJS

tmodJS实现了{{include}}的功能,语法也基本与artTemplate一致,所以学习成本来说是极低的。

只需要安装tmodjs命令行工具:

npm install -g tmodjs

index.html页面实际如下:

{{include './header'}}

<div id="container">
    {{include './public/banner'}}

    <!-- 判断主体内容 -->
    {{if position == 'temppage'}}

    {{include './public/tempcont'}}

    {{/if}}

</div>

{{include './footer'}}

引用的公共区域以banner为例,内容如下,可以设置变量

<!-- banner开始 -->

<div class="banner">
    <div class="u-container">
        <div class="banner-content">
            <h1>{{title}}</h1>
            <p class="info">{{description}}</p>
        </div>
    </div>
</div>


<!-- banner结束 -->

通过运行

tmod

会默认将公共文件打包压缩为template.js,页面加载此文件,从而实现{{include}},然后其他执行如第一种方法。

从整体来看,除了实现引用{{include}},tmod依然没有解决我们后端直接输出html页面的需求。

好在我们还有第三种方法:

artTemplate的node版本

好了,支持

  • 支持预编译
  • 直接编译输出html页面
  • 命令简单

安装

npm install art-template

demo:

index.html

<html>
<head>
<meta charset='utf-8'>
<title>模板</title>
</head>

<body>
     <div id=”main”>
        {{include './common/header'}}
          <ul>
               {{each list}}
               <li>编号:{{$value.id}} &nbsp;&nbsp;姓名:{{$value.name}}</a></li>
               {{/each}}
          </ul>
     </div>
</body>
</html>

node中编译,将index.html输出为完整的静态页test.html

var fs = require('fs');
var template = require('art-template');
var datalist = require('./data.json'); // 引入数据

//渲染模板
var html = template('./index', datalist);
fs.writeFileSync('./test.html', html);

data.json内容

{"list": 
    [{"id":1, "name":"张三2"}, {"id":2, "name":"李四"}]
}

最终test.html输出结果

<html>
<head>
<meta charset='utf-8'>
<title>模板</title>
</head>
<body>
     <div id=”main”>
        <!-- 导航开始 -->
        ...
        <!-- 导航结束 -->
          <ul>

               <li>编号:1 &nbsp;&nbsp;姓名:张三2</a></li>

               <li>编号:2 &nbsp;&nbsp;姓名:李四</a></li>

          </ul>
     </div>
</body>
</html>

下边就是用node将整个文件复制编译出了,有时间再写。