模板引擎(Template Engine)是一个将页面模板和数据结合起来生成 html 的工具。上例中,我们只是返回纯文本给浏览器,现在我们修改代码返回一个 html 页面给浏览器。
## 3.3.1 ejs
模板引擎有很多,[ejs](https://www.npmjs.com/package/ejs) 是其中一种,因为它使用起来十分简单,而且与 express 集成良好,所以我们使用 ejs。安装 ejs:
```
npm i ejs --save
```
修改 index.js 如下:
**index.js**
```
var path = require('path');
var express = require('express');
var app = express();
var indexRouter = require('./routes/index');
var userRouter = require('./routes/users');
app.set('views', path.join(__dirname, 'views'));// 设置存放模板文件的目录
app.set('view engine', 'ejs');// 设置模板引擎为 ejs
app.use('/', indexRouter);
app.use('/users', userRouter);
app.listen(3000);
```
通过 `app.set` 设置模板引擎为 ejs 和存放模板的目录。在 myblog 下新建 views 文件夹,在 views 下新建 users.ejs,添加如下代码:
**views/users.ejs**
```
<!DOCTYPE html>
<html>
<head>
<style type="text/css">
body {padding: 50px;font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;}
</style>
</head>
<body>
<h1><%= name.toUpperCase() %></h1>
<p>hello, <%= name %></p>
</body>
</html>
```
修改 routes/users.js 如下:
**routes/users.js**
```
var express = require('express');
var router = express.Router();
router.get('/:name', function(req, res) {
res.render('users', {
name: req.params.name
});
});
module.exports = router;
```
通过调用 `res.render` 函数渲染 ejs 模板,res.render 第一个参数是模板的名字,这里是 users 则会匹配 views/users.ejs,第二个参数是传给模板的数据,这里传入 name,则在 ejs 模板中可使用 name。`res.render` 的作用就是将模板和数据结合生成 html,同时设置响应头中的 `Content-Type: text/html`,告诉浏览器我返回的是 html,不是纯文本,要按 html 展示。现在我们访问 `localhost:3000/users/haha`,如下图所示:
![](https://box.kancloud.cn/34db89f5aa65a966215a2a6733bee79c_487x275.png)
上面代码可以看到,我们在模板 `<%= name.toUpperCase() %>` 中使用了 JavaScript 的语法 `.toUpperCase()` 将名字转化为大写,那这个 `<%= xxx %>` 是什么东西呢?ejs 有 3 种常用标签:
1. `<% code %>`:运行 JavaScript 代码,不输出
2. `<%= code %>`:显示转义后的 HTML内容
3. `<%- code %>`:显示原始 HTML 内容
> 注意:`<%= code %>` 和 `<%- code %>` 都可以是 JavaScript 表达式生成的字符串,当变量 code 为普通字符串时,两者没有区别。当 code 比如为 `<h1>hello</h1>` 这种字符串时,`<%= code %>` 会原样输出 `<h1>hello</h1>`,而 `<%- code %>` 则会显示 H1 大的 hello 字符串。
下面的例子解释了 `<% code %>` 的用法:
**Data**
```
supplies: ['mop', 'broom', 'duster']
```
**Template**
```
<ul>
<% for(var i=0; i<supplies.length; i++) {%>
<li><%= supplies[i] %></li>
<% } %>
</ul>
```
**Result**
```
<ul>
<li>mop</li>
<li>broom</li>
<li>duster</li>
</ul>
```
更多 ejs 的标签请看 [官方文档](https://www.npmjs.com/package/ejs#tags)。
## 3.3.2 includes
我们使用模板引擎通常不是一个页面对应一个模板,这样就失去了模板的优势,而是把模板拆成可复用的模板片段组合使用,如在 views 下新建 header.ejs 和 footer.ejs,并修改 users.ejs:
**views/header.ejs**
```
<!DOCTYPE html>
<html>
<head>
<style type="text/css">
body {padding: 50px;font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;}
</style>
</head>
<body>
```
**views/footer.ejs**
```
</body>
</html>
```
**views/users.ejs**
```
<%- include('header') %>
<h1><%= name.toUpperCase() %></h1>
<p>hello, <%= name %></p>
<%- include('footer') %>
```
我们将原来的 users.ejs 拆成出了 header.ejs 和 footer.ejs,并在 users.ejs 通过 ejs 内置的 include 方法引入,从而实现了跟以前一个模板文件相同的功能。
> 小提示:拆分模板组件通常有两个好处:
>
> 1. 模板可复用,减少重复代码
> 2. 主模板结构清晰
> 注意:要用 `<%- include('header') %>` 而不是 `<%= include('header') %>`
- 使用 Express + MongoDB 搭建多人博客
- 1.1 Node.js 的安装与使用
- 1.2 MongoDB 的安装与使用
- 2.1 require
- 2.2 exports 和 module.exports
- 2.3 Promise
- 2.4 环境变量
- 2.5 package.json
- 2.6 npm 使用注意事项
- 3.1 初始化一个 Express 项目
- 3.2 路由
- 3.3 模板引擎
- 3.4 Express 浅析
- 4.1 开发环境
- 4.2 准备工作
- 4.3 配置文件
- 4.4 功能设计
- 4.5 页面设计
- 4.6 连接数据库
- 4.7 注册
- 4.8 登出与登录
- 4.9 文章
- 4.10 留言
- 4.11 404 页面
- 4.12 错误页面
- 4.13 日志
- 4.14 测试
- 4.15 部署