模板引擎

动态生成 html 的工具,模板引擎有很多,这里介绍几个,其他的类似,原理都类似的。

pug

安装

我们可以通过 npm i pug 来安装

服务器脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// index.js
const Koa = require("koa");
const Router = require("koa-router");
const views = require("koa-views");
let app = new Koa();
let router = new Router();
app.use(
views(__dirname + "/views", {
map: {
html: "pug",
},
})
);
router.get("/", async (ctx) => {
// ctx.body = "hello";
let users = [
{ name: "张三", age: 20, height: "178cm" },
{ name: "李四", age: 25, height: "179cm" },
{ name: "王五", age: 26, height: "180cm" },
];
await ctx.render("index.pug", {
data: "我是数据",
users,
});
});
app.use(router.routes());
app.listen(3000);

标签

pug 是单标签,通过缩进& 空格来表示级别关系的,类似 Python 的语法,举个 🌰

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//- index.pug
doctype html
html(lang="en")
head
meta(charset="UTF-8")
meta(http-equiv="X-UA-Compatible", content="IE=edge")
meta(name="viewport", content="width=device-width, initial-scale=1.0")
title Document
body
h1 我是标题
div 我是和 h1 同级的 div
div(class='class1') 我是类名为 class1 的 div
span 我是 div 下的 span
//- 生成类名为 class2 的 div 标签
.class2(style={width:'100px',height:'100px',background:'skyblue'}) 声明行内样式
#myid 我是 id 为 myid 的 div

声明内部样式

声明内部样式需要在 meta 同级添加 style.,然后跟写正常的样式是一样的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
doctype html
html(lang="en")
head
meta(charset="UTF-8")
meta(http-equiv="X-UA-Compatible", content="IE=edge")
meta(name="viewport", content="width=device-width, initial-scale=1.0")
title Document
//- style. 不要丢下这个点
style.
.class1{
width:200px;
height:100px;
background-color:pink;
}

定义 & 使用变量

在声明变量前面加 -

1
2
3
//- 定义并且使用变量
- let str = '你好'
p #{str}

也可以在 render 的时候传递数据

index.js 脚本内容:
在这里插入图片描述
pug 页面:
在这里插入图片描述

呈现的页面:在这里插入图片描述

循环

循环有两种,一种是 each 循环:

1
2
3
ul
each item, index in users
li 姓名是 #{item.name}

另一种是 for 循环:

1
2
- for (let i = 0; i < 4; i++)
span 我是 #{i + 1}

Case / when

跟其他语言里的 Switch case 差不多的功能。

1
2
3
4
5
6
7
8
- let num = 1
case num
when 1
p num 是一
when 2
p num 是二
default
p num 是其他值

定义 & 调用函数

声明函数用 mixin,调用函数用+

1
2
3
4
5
6
7
8
9
10
11
12
//- 定义函数
mixin mydiv
div 我是非常常用的div

//- 调用函数
+mydiv

//- 传递参数
mixin pet(name,sex)
p 这是一只#{name} 它的性别是#{sex};
+pet("狗狗","公")
+pet("猫","母")

引入模板

include + 文件名 来引入模板

1
2
//- 公共模板,比方说页眉和页脚
include common.pug

引入脚本

1
2
//- 引入脚本
script((type = "text/javascript")).console.log("我是js脚本");

nunjunks

官网戳这里!,这个如果改了 html 的话,需要重新启动 node 更新一下,因为它不会监控 html 的更新(比较麻烦)

服务器脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
const Koa = require("koa");
const Router = require("koa-router");
const nunjucks = require("koa-nunjucks-2");
let app = new Koa();
let router = new Router();
app.use(
nunjucks({
ext: "html", //.njk
path: __dirname + "/views",
nunjucksConfig: {
trimBlocks: true, //防止Xss漏洞;
},
})
);
router.get("/", async (ctx) => {
// ctx.body = "hello";
await ctx.render("index", {
username: "张三",
num: 2,
arr: [
{
name: "张三",
age: 20,
},
{
name: "李四",
age: 28,
},
],
str: "hello world",
});
});
router.get("/son1", async (ctx) => {
await ctx.render("son1");
});

router.get("/import", async (ctx) => {
await ctx.render("import");
});
app.use(router.routes());
app.listen(8000);

变量

引用变量还是使用插值表达式,变量是从上下文中获取的。

1
<p>用户名是:{{ username }}</p>

判断语句

1
2
3
4
5
6
7
{% if num > 3 %}
<p>num值大于三</p>
{% elseif num<3 %}
<p>num值小于三</p>
{% else %}
<p>num值等于三</p>
{% endif %}

循环语句

1
2
3
4
5
<ul>
{% for item in arr %}
<li>姓名是:{{item.name}};年龄是:{{item.age}};</li>
{% endfor %}
</ul>

过滤器

这个是官网的例子,其中 capitalize 代表首字母大写。

1
2
3
4
5
{
{
str | replace("world", "世界") | capitalize;
}
}

模板继承

在这里插入图片描述

1
2
3
4
5
6
7
8
9
10
11
12
13
// parent.html
<div>
<p>我是父级模板</p>
{% block left %}
<p>左边内容</p>
{% endblock %}
{% block right %}
右边内容
{% endblock %}
{% block somevalue %}
一些数据
{% endblock %}
</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// son.js
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
{% extends 'parent.html' %}
{% block left %}
我是son1里左侧内容
{% endblock %}
{% block right %}
我是son1里右侧侧内容
{% endblock %}
{% block somevalue %}
{{super()}}
{% endblock %}
</body>
</html>

宏标签

macro 官网上的解释

现在可以当做函数来使用

1
2
3
4
5
{% macro person(name, sex) %}
<p>我是{{name}},我的性别是{{sex}}</p>
{% endmacro %}

{{person('小明','男')}}

引入

include 引入
1
{% include 'footer.html' %}
import 引入

在这里插入图片描述