企业🤖AI Agent构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
模板引擎(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') %>`