Node.js Web 模板引擎 Eta 的简单使用
在 Node.js 中,如果需要在服务端渲染 HTML 就需要通过拼接字符串的方式来实现。简单的 HTML 使用 ES6 的字符串模板也能勉强凑合,但是复杂一些的,需要涉及到循环之类的写起来就不太方便了,后期也不好维护。
模板引擎可以让你在单独的文件中按照正常的格式来编写 HTML,在 HTML 模板中也可以使用变量、循环、简单罗纪判断之类的功能。模板引擎在执行的时候,会把 HTML 中的变量之类的替换为实际的数据,然后输出 HTML String。
Node.js 有很多第三方的模板引擎,最常见的包括:
- Handlebars
- EJS
- Mustache
- pug
- art-template
我这里使用的 Eta 是一个比较轻量的模板引擎,它的语法和 EJS 的差不多,比较简单。Eta 可以搭配 Express 之类的 Web 框架使用,也可以不使用 Web 框架,直接在 Node.js 中使用,Eta 执行完成后可以直接返回 HTML String。
安装和基本配置
初始化项目:
npm init -y
使用 npm 安装 Eta:
npm install eta --save
可以创建一个 templates
目录来存储模板文件,我这里也会使用 templates
目录来存储模板文件。
下面直接使用 Eta,不使用 Web 框架,在 templates
中创建一个 index.eta
文件作为 HTML 模板:
<a href="<%= it.url %>"><%= it.name %></a>
上面的链接 href
和 html
都是动态生成的,下面使用 Eta 转换 index.eta
:
const { Eta } = require('eta');
const path = require('path');
// 初始化 eta,把 templates 设置为模板文件夹
const eta = new Eta({views: path.join(__dirname, 'templates')});
// 用于填充模板的数据
const data = {url: 'https://www.misterma.com', name: `Mr. Ma's Blog`};
// 执行 eta 模板转换
const html = eta.render('index', data);
// 在控制台输出转换后的 HTML
console.log(html);
转换后的 index.eta
模板如下:
<a href="https://www.misterma.com">Mr. Ma's Blog</a>
在 Express 中使用 Eta
下面在 Express 的项目中使用 Eta,模板使用的还是 templates/index.eta
:
const { Eta } = require('eta');
const express = require('express');
const path = require('path');
const app = express();
// 初始化 Eta
const eta = new Eta({
views: path.join(__dirname, 'templates'),
cache: false
});
// 设置使用的模板引擎和模板后缀
app.engine('ega', eta.render);
app.set('view engine', 'eta');
// 用于填充模板的数据
const data = {url: 'https://www.misterma.com', name: `Mr. Ma's Blog`};
// 处理 GET 请求
app.get('/', (req, res) => {
// 返回 Eta 转换后的 HTML
res.send(eta.render('index', data));
});
// 启动 http 服务
app.listen(7777, () => {
console.log('server start http://localhost:7777');
});
使用浏览器访问 http://localhost:7777
也能看到 Mr. Ma's Blog
链接。
Eta 在 Express 中不支持使用 Express 的 res.render
输出,需要使用 Express 的 res.send
输出转换后的 HTML String。
Eta 基本语法
Eta 的模板文件使用 .eta
后缀,在模板文件中,传入 Eta 的数据都可以通过 it
变量来获取,输出数据需要写在 <%= %>
标记中。
下面是一个简单的对象:
const data = {name: '肖恩', age: 17};
eta.render('index', data);
Eta 模板:
<p>我是 <%= it.name %>,我今年 <%= it.age %> 岁</p>
转换后的 HTML 如下:
<p>我是 肖恩,我今年 17 岁</p>
默认情况下 Eta 会对 HTML 代码进行转译,也就是说 HTML 在浏览器中也会显示为 HTML 代码,如果需要 HTML 效果可以使用 <%~ %>
标记输出:
%~ it.html %>
要在 Eta 中使用 JavaScript 可以写在 <% %>
标记中:
<% it.name = '哈哈哈' %>
<%= it.name %>
如果你对 Eta 的标记,包括 <% %>
、<%= %>
、<%~ %>
不满意的话,也可以在初始化 Eta 的时候自定义。Eta 模板内的 it
变量也可以自定义。
关于 Eta 自定义设置之类的可以参考后面的 选项配置
。
在模板中引入其它模板
在 HTML 中可能会有一些每个页面都会用到的部分,比如 header
、footer
、导航栏、侧边栏,这些部分没必要在每个页面中都写一份。
下面把一个 HTML 页面拆分为 header
和 footer
:
header.eta
:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title><%= it.pageTitle %></title>
</head>
<body>
footer.eta
:
</body>
</html>
下面在 index.eta
中引入 header
和 footer
来组成一个完整的页面:
<%~ include('./header', {pageTitle: it.pageTitle}) %>
<h1><%= it.text %></h1>
<%~ include('./footer') %>
我使用的数据如下:
const data = {pageTitle: '一个完整的页面', text: 'Hello'};
最终的 index 页面如下:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>一个完整的页面</title>
</head>
<body>
<h1>Hello</h1>
</body>
</html>
在 Eta 模板中使用 include()
函数可以引入一个 Eta 模板,第一个参数是模板文件名称,不需要后缀,第二个参数是数据,include
需要写在 <%~ %>
标记里。
我上面的 header
的页面标题是动态输出的,我在 index
中引入 header
的时候也传入了一个 pageTitle
用于页面标题。
条件判断
下面根据条件显示内容:
<% if (it.login) { %>
<a>用户信息</a>
<a>退出登录</a>
<% } else { %>
<a>登录</a>
<a>注册</a>
<% } %>
上面如果 login
为 true
就会输出 用户信息
和 退出登录
链接,否则就输出 登录
和 注册
链接。
循环
下面是一个数组对象:
const data = [
{url: 'https://www.misterma.com', name: `Mr. Ma's Blog`},
{url: 'https://github.com/changbin1997', name: 'Github'}
];
下面通过 forEach
循环的方式输出数据:
<% it.forEach(link => { %>
<a href="<%= link.url %>" ><%= link.name %></a>
<% }) %>
循环输出的 HTML 如下:
<a href="https://www.misterma.com" >Mr. Ma's Blog</a>
<a href="https://github.com/changbin1997" >Github</a>
同样的数据,下面使用 for
循环输出:
<% for (let i = 0;i < it.length;i ++) { %>
<a href="<%= it[i].url %>" ><%= it[i].name %></a>
<% } %>
API 说明
要使用 Eta 需要先使用:
const eta = new Eta(options);
初始化 Eta。
渲染模板文件可以使用:
eta.render('index', {name: 'Hello'});
第一个参数是模板文件名称,不需要加 eta
后缀,第二个参数是数据。
如果需要异步渲染可以使用:
eta.renderAsync('index', {name: 'Hello'}).then(result => {
res.send(result);
});
renderAsync
和 render
的参数是一样的,renderAsync
渲染完成后会返回一个 Promise。
如果需要在 JS 中使用字符串模板可以使用 renderString
渲染,下面是一个字符串模板:
// 字符串模板
const templateStr = `
<a href="<% it.url %>"><%= it.name %></a>
`;
// 数据
const data = {name: `Mr. Ma's Blog`, url: 'https://www.misterma.com'};
// 渲染字符串模板
const html = eta.renderString(templateStr, data);
renderString
的第一个参数是模板字符串,第二个参数是数据。
异步方式渲染字符串模板可以使用 renderStringAsync
,renderStringAsync
和 renderString
的参数是一样的,只是 renderStringAsync
返回的是 Promise。
配置选项
在使用 new Eta
初始化的时候需要传入一个配置对象,下面是一些配置选项说明:
// 配置选项
const options = {
// 设置模板文件夹的位置
views: path.join(__dirname, 'templates'),
// 对 XML 和 HTML 代码进行自动转译,默认为 true
autoEscape: false,
// 是否缓存模板,默认为 false
cache: false,
// 保存已解析文件路径的缓存,默认为 false
cacheFilepaths: false,
// debug 模式,出错时对错误信息进行美化输出,默认为 false
debug: false,
// 删除 HTML 中的空格,默认为 false
rmWhitespace: false,
// 自定义 Eta 模板标记符,默认为 ['<%', '%>']
tags: ['<?eta', '?>'],
// 在 Eta 模板内不使用 it 变量,直接访问传入的对象,默认为 false
useWith: false,
// Eta 模板内数据变量的名称,默认为 it
varName: 'it',
// 解析设置
parse: {
// 在 Eta 模板内使用 JavaScript 的前缀,默认没有前缀,也就是在 <% %> 使用 JS 代码
exec: '',
// 在 Eta 模板内输出内容的前缀,默认为 '=' ,也就是在 <%= %> 内输出
interpolate: '=',
// 在 Eta 模板内输出原始内容的前缀,默认为 '~' ,也就是在 <%~ %> 内输出 HTML 代码和引入模板
raw: '~'
}
};
// 初始化 Eta
const eta = new Eta(options);
以上就是 Eta 的基本使用。Eta 模板比较简单,Eta 标记之类的都可以按照自己的习惯配置,简单看一下说明就可以直接上手使用。
版权声明:本文为原创文章,版权归 Mr. Ma's Blog 所有,转载请联系博主获得授权。
本文地址:https://www.misterma.com/archives/935/
如果对本文有什么问题或疑问都可以在评论区留言,我看到后会尽量解答。