前端战五渣学前端——模板引擎(Handlebars.js)

6,498 阅读6分钟

最近想着写点什么实用的工具,算是偶然间又接触到了这个名词模板引擎,所以又专门的查了一下,相信在这个三大框架(😜也可能是两大框架)大行其道的时候,多少接触过,只是不知道这就是模板引擎的功劳。


本文巨简单,只是简单介绍了一下,更多api请查看相关文档


接触过的模板

模板引擎最明显的特征就是用了花括号{{ }}(但不限于{{ }},也可能是别的特定符号),里面写上key值,渲染出来就是key对应的value

vue中的模板

vue中是明显的使用了模板语法,他们的文档中也很明确的写了

Vue.js 使用了基于 HTML 的模板语法,允许开发者声明式地将 DOM 绑定至底层 Vue 实例的数据。所有 Vue.js 的模板都是合法的 HTML ,所以能被遵循规范的浏览器和 HTML 解析器解析。在底层的实现上,Vue 将模板编译成虚拟 DOM 渲染函数。结合响应系统,Vue 能够智能地计算出最少需要重新渲染多少组件,并把 DOM 操作次数减到最少。如果你熟悉虚拟 DOM 并且偏爱 JavaScript 的原始力量,你也可以不用模板,直接写渲染 (render) 函数,使用可选的 JSX 语法。

上面我们我们可以看出来,我们只是在标签中写上了{{ message }},但是渲染粗来的,确实对应的下面声明的data中的message的值,当然,vue在中间做了很多事情,还有diff算法之类的,但是我们今天不涉及diff算法的东西,只是了解一下前端中的模板引擎

还有,vue中还有一种实现——单文件组件

其实差不多,一个.vue的文件,经过webpack的loader解析,再最终显示出来。我们只需要看这个花括号的实现,跟上面的是一样的

lodash中的模板

lodash专门有一个api的名字就是template_.template([string=''], [options={}])这么使用

lodash中的模板看起来跟vue的不太一样是不是,他用的<%= %>这种东西来包住变量名,所以我一开始说了不局限于{{ }}这种花括号

其他的模板

在我刚接触前端的时候,我之前的博客中说过,我使用过backbone.js,这个以来的又是underscore.js中的模板方法,这也是一个通过模板更换页面内容的库(或者框架),还有在前后端没有分离之前,后端也会有模板。

总结什么是模板

什么是模板呢,我的理解就是我事先喜好一套模板,然后根据数据不同,更改里面的数据就行了,而模板结构是不会变的。怎么说好理解一些呢,就是现在很多外包给别人做官网的,他们会事先写好很多套官网,各式各样的,然后再根据客户的不同需求,更换里面的内容,事前写好的这个官网就算是模板,然后再更换里面的公司名称、联系电话和图片等一些东西,就可以快速产出了


当然,我今天的目的不是讲什么是模板,只是为了先说清楚是什么东西,下面就要讲这个模板引擎Handlebars.js了,因为我要写的工具会用到这个,所以我就讲一下怎么使用,希望能对以后用到这个东西的同学能起到一点点的帮助吧

正文开始

<script type="text/template"><template>

可能很多小伙伴没见过<script type="text/template">script标签的type竟然还有这种属性,相对于script标签的一个属性值,<template>标签写过vue的都见过,都知道是可以在里面写上div等标签的。那这两个标签到底有什么用呢。来看

很明显,什么都没有~这就是这两个标签的特性,浏览器并不会直接解析这两个标签里面的标签,神奇不

浏览器会忽略这些标签,这就允许我们在里面放置任何内容,然后可以在以后用到的时候取出来给模板库使用了,但是<template>这个标签坑爹的IE是不支持的。

Handlebars.js(模板引擎库)

Handlebars.js给你提供了牛逼的功能,可以让你很方便的构建语义化的模板,Handlebars.js兼容Mustache.js的模板,在大部分情况下,我们可以用Handlebars.js取代Mustache.js

Handlebars.js可以说是Mustache.js的一个扩展,所以用这个就ok了。那我们到底怎么用呢?往下看

最简单的使用

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>模板引擎</title>
  <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
  <script src="https://cdn.bootcss.com/handlebars.js/4.1.2/handlebars.min.js"></script>
</head>
<body>
  <div id="root"></div>

  <template id="template">
    <p>名字: {{ name }}</p>
    <p>年龄: {{ age }}</p>
  </template>

  <script>
    $(function() {
      var data = {
        name: '前端战五渣',
        age: 16
      };
      var root = $('#root'); // 获取根节点,需要更换内容的标签
      var htmlNode = $("#template").html(); // 获取标签内容
      var templateWithoutData = Handlebars.compile(htmlNode); // 生成没有数据的模板
      var templateWithData = templateWithoutData(data); // 向没有数据的模板传数据
      root.html(templateWithData); // 把有数据的模板添加到页面
    })
  </script>
</body>
</html>

上面的代码运行结果就是

这是最简单的实现了,把data中的数据渲染到了页面上,下面是我写的一个小小的切换页面的功能

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>模板引擎</title>
  <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
  <script src="https://cdn.bootcss.com/handlebars.js/4.1.2/handlebars.min.js"></script>
</head>
<body>
  <div>
    <p>我这是导航</p>
    <button data-place="one">真新镇</button>
    <button data-place="two">常磐市</button>
    <button data-place="three">常磐森林</button>
  </div>
  <div id="content"></div>

  <template id="one">
    <h1>{{ name }}</h1>
    <p>我是第一个页面</p>
  </template>

  <template id="two">
    <h1>{{ name }}</h1>
    <p>我是第二个页面</p>
  </template>

  <template id="three">
    <h1>{{ name }}</h1>
    <p>我是第三个页面</p>
  </template>

  <script>
    var one = { name: '真新镇' };
    var two = { name: '常磐市' };
    var three = { name: '常磐森林' };
    $(function () {
      var content = $('#content');
      $('button').on('click', function () {
        var target = $(this).attr('data-place');
        var htmlNode = $('#' + target).html();
        var templateWithoutData = Handlebars.compile(htmlNode);
        var templateWithData;
        switch(target) {
          case 'one':
            templateWithData = templateWithoutData(one);
            break;
          case 'two':
            templateWithData = templateWithoutData(two);
            break;
          case 'three':
            templateWithData = templateWithoutData(three);
            break;
        }
        content.html(templateWithData);
      })
    })
  </script>
</body>
</html>

helper

文档什么的都没有解释这个helper是什么意思,按我的理解就是一些内置的语法,我们可以用,也可以自定义helper,这里就不涉及了

if helper

这个就是我们可以在模板里面写一些if else的逻辑了,判断现隐什么的

<div id="root"></div>

<template id="template">
    {{#if job}}
    <p>名字: {{ name }}</p>
    <p>年龄: {{ age }}</p>
    <p>工作: {{ job }}</p>
    {{else}}
    <p>还没有工作</p>
    {{/if}}
</template>

<script>
$(function() {
  var data = {
    name: '前端战五渣',
    age: 20,
    job: '前端开发'
  };
  var root = $('#root'); // 获取根节点,需要更换内容的标签
  var htmlNode = $("#template").html(); // 获取标签内容
  var templateWithoutData = Handlebars.compile(htmlNode); // 生成没有数据的模板
  var templateWithData = templateWithoutData(data); // 向没有数据的模板传数据
  root.html(templateWithData); // 把有数据的模板添加到页面
})
</script>

按着上面的代码写的话,data中job是有值的,我就可以在最后的渲染中显示出来

假如我把job删掉

var data = {
    name: '前端战五渣',
    age: 20,
    job: ''
  };

就都不显示了,就显示{{else}}后面的东西了,这个很类似jsx的语法

模板中的注释

我们在模板中怎么写注释呢,直接看

<template id="template">
    {{#if job}}
    <p>名字: {{ name }}</p>
    <p>年龄: {{ age }}</p>
    <p>工作: {{ job }}</p>
    {{else}}
    <!-- 我是注释我是注释 -->
    {{! 我是注释我是注释  }}
    {{!-- 我是注释我是注释 --}}
    <p>还没有工作</p>
    {{/if}}
</template>

我们知道,在HTML中,注释是<!-- -->是这么写的,没错,但是这个是会在html中显示出来的,那我们如何写注释才能不在页面中显示出来呢,那就是我代码中写的{{! }} 和 {{!-- --}}

总结

其实这个能支持模板语言,还有if else已经够我自己要写的工具了,相关的Handlebars.js的文档也不是很多,可以看看的,一会就能看完。其实这个东西用是不难的,如果自己写一套模板引擎,那才是牛逼的人呢


我是前端战五渣,一个前端界的小学生。