Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
153 lines (110 sloc) 4.45 KB

模板引擎(Template Engine)是一个将页面模板和数据结合起来生成 html 的工具。上例中,我们只是返回纯文本给浏览器,现在我们修改代码返回一个 html 页面给浏览器。

3.3.1 ejs

模板引擎有很多,ejs 是其中一种,因为它使用起来十分简单,而且与 express 集成良好,所以我们使用 ejs。安装 ejs:

npm i ejs --save

修改 index.js 如下:

index.js

const path = require('path')
const express = require('express')
const app = express()
const indexRouter = require('./routes/index')
const 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

const express = require('express')
const 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,如下图所示:

上面代码可以看到,我们在模板 <%= 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 的标签请看 官方文档

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') %>

上一节:3.2 路由

下一节:3.4 Express 浅析

You can’t perform that action at this time.