模板引擎
目标
- 能够使用模板引擎渲染数据
- 能够使用模板引擎进行原文输出
- 能够使用循环输出数据
- 能够知道如何引用子模板
- 能够知道如何如何进行模板继承
基本概念(★★★)
模板引擎是第三方模块。
让开发者以更加友好的方式拼接字符串,使项目代码更加清晰更加易于维护
[外链图片转存失败(img-e5YrlUW6-1568473328611)(images/artTemplate.png)]
art-template模板引擎
入门使用(★★★)
-
利用
npm
命令下载art-template
库npm install art-template
-
创建
js
文件,引入art-template
库const trempalte = require('art-template');
-
引入拼接的数据源
//引入path库 const path = require('path'); //拼接路径,这里最好用绝对路径 const views = path.join(_dirName,'views','index.art'); //关联到 template里面 const html = template(views,{ name: '德玛西亚' });
-
创建.art 渲染模板
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <!--标准语法--> <p>{{ name }}</p> <!--原生语法--> <p><%= age%></p> </body> </html>
输出语句
标准语法用 {{}}(★★★)
在大括号里面可以进行逻辑运算
<p>{{ 1 + 1 }}</p>
<p>{{ 1 + 1 == 2 ? '相等' : '不相等' }}</p>
<p>{{ content }}</p>
如果说需要解析html标签,需要在变量前面加 @ 符号
<p>{{@ content }}</p>
原生语法 <%= %>
可以进行逻辑运算
<p><%= 1 + 2%></p>
<p><%= 1 + 1 == 2 ? '相等' : '不相等' %></p>
<p><%= content%></p>
如果说需要解析html标签,需要在变量前面加 - 符号
<p><%- content%></p>
条件判断
标准语法 {{if 条件}} … {{/if}} (★★★)
{{if age > 18}}
年龄大于18
{{else if age < 15 }}
年龄小于15
{{else}}
年龄不符合要求
{{/if}}
原生语法 <% if (value) { %> … <% } %>
<% if (age > 18) { %>
年龄大于18
<% } else if (age < 15) { %>
年龄小于15
<% } else { %>
年龄不符合要求
<% } %>
循环
标准语法 {{each 数据}} {{/each}}(★★★)
<ul>
{{each users}}
<li>
{{$value.name}}
{{$value.age}}
{{$value.sex}}
</li>
{{/each}}
</ul>
原生语法 <% for() { %> <% } %>
<ul>
<% for (var i = 0; i < users.length; i++) { %>
<li>
<%=users[i].name %>
<%=users[i].age %>
<%=users[i].sex %>
</li>
<% } %>
</ul>
子模版
使用子模板可以将网站公共区块(头部、底部)抽离到单独的文件中
标准语法 {{include ‘模板’}}(★★★)
{{ include './common/header.art' }}
...
{{ include './common/footer.art' }}
原生语法 <%include(‘模板’) %>
<% include('./common/header.art') %>
...
<% include('./common/footer.art') %>
模板继承(★★★)
使用模板继承可以将网站HTML骨架抽离到单独的文件中,其他页面模板可以继承骨架文件
[外链图片转存失败(img-jm4wJH3l-1568473328616)(images/模板继承.png)]
但是在html骨架中,有一些内容是不一样的,例如引入的css不同,引入的js脚本不同,所以我们可以通过在骨架中先预留几个位置,让其它功能页面在继承的使用,引入相应自己的文件即可
[外链图片转存失败(img-af4LFRCN-1568473328618)(images/骨架预留.png)]
使用
-
现在骨架标签中设定预留位置
<!doctype html> <html> <head> <meta charset="utf-8"> <title>HTML骨架模板</title> <!-- 预留位置,打上标记为 head--> {{block 'head'}}{{/block}} </head> <body> <!-- 预留位置,打上标记为 content--> {{block 'content'}}{{/block}} </body> </html>
-
在另外的 模板文件中利用 extends 来进行引入
<!--index.art 首页模板--> <!--extend 进行继承, 后面跟需要继承的文件路径--> {{extend './layout.art'}} {{block 'head'}} <link rel="stylesheet" href="custom.css"> {{/block}} {{block 'content'}} <p>{{name}}</p> {{/block}}
-
在
js
文件里面输入内容,利用art-templare
进行模板渲染//引入 template 库 const template = require('art-template'); //引入 path 库,用来处理路径 const path = require('path'); //生成路径 const views = path.join(_dirName,'views','index.art'); //利用template 进行渲染 const html = template(views,{ name: '德玛西亚' });
模板配置(★★★)
在模板引擎中,如果想使用第三方模块的一些方法,默认我们是不能直接使用的,必须要通过template模块给我们提供的方法,把第三方模块的对象当作变量传递进入
语法:
template.defaults.imports.自定义变量名 = 第三方模板对象;
示例代码
//1. 需要先 下载第三方模块 npm install dateformat
//2. 模板引擎第三方库
const template = require('art-template');
//3. 处理路径的第三方模块
const path = require('path');
const views = path.join(__dirname, 'views', 'index.art');
//4. 格式化日期的第三方模块
const dateFormart = require('dateformat');
//5. 不能直接使用,需要通过 template进行模板配置
template.defaults.imports.dateFormart = dateFormart;
const html = template(views, {
time: new Date(),
})
console.log(html);
//渲染模板
{{extend './common/layout.art'}}
{{block 'css'}}
<link href='style.css' />
{{/block}}
{{block 'content'}}
<p>{{ dateFormart(time,'yyyy-MM-dd hh:mm:ss') }}</p>
{{/block}}
输出结果
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<link href='style.css' />
</head>
<body>
<p>2019-22-16 01:04:17</p>
</body>
</html>
设置模板根目录(★★★)
有的时候我们引入模板会比较多,如果一个一个去进行引入比较麻烦,所以我们可以通过引入模板根目录的形式去进入,这样当我们引入模板文件的时候,它会根据我们传递的名字自动匹配
语法:
template.defaults.root = path.join(__dirname, 模板文件夹名称);
设置模板默认后缀(★★)
可以去设置默认的后缀名,这样我们引入文件省略后缀名
语法:
template.defaults.extname = '.html';
案例介绍 – 学生档案管理(★★)
目标
- 熟悉模板引擎的应用场景
- 能够理解其思路
- 能够创建web服务器
- 能够链接数据库
- 能够创建学生集合规则
- 参照案例能够写出学生档案管理
**知识点:**http请求响应、数据库、模板引擎、静态资源访问
[外链图片转存失败(img-gpqrdITl-1568473328620)(images/学生档案管理.png)]
制作流程
- 建立项目文件夹并生成项目描述文件
- 创建网站服务器实现客户端和服务器端通信
- 连接数据库并根据需求设计学员信息表
- 创建路由并实现页面模板呈递
- 实现静态资源访问
- 实现学生信息添加功能
- 实现学生信息展示功能
实现思路
引入 http 模块,创建web服务
//引入http模块,用来创建服务器
const http = require('http');
//开启服务
const server = http.createServer();
//监听请求
server.on('request', (req, res) => {
res.end('<h1>ok</h1>');
})
//监听端口号
server.listen(8080);
console.log('启动服务器成功');
需要使用到服务器,下载 mongoose
第三方库
//1. npm install mongoose 下载mongodb第三方库
//2. 引入数据库模块
const mongoose = require('mongoose');
//3. 链接数据库
mongoose.connect('mongodb://localhost/students', { useNewUrlParser: true })
.then(success => console.log('链接成功'))
.catch(error => console.log(error));
定义用户规则,创建用户集合(定义用户表结构)
const mongoose = require('mongoose');
const student = mongoose.Schema({
name: {
//类型
type: String,
//是否是必须要填写
require: true,
//最小长度
minlength: 2,
//最大长度
maxlength: 20
},
age: {
type: Number,
min: 10,
max: 25
},
email: String,
//爱好,数组形式
hobbies: [String],
collage: String,
date: {
type: Date,
//默认时间是当前时间
default: Date.now()
}
});
//给数据库定义表结构
const studentEntity = mongoose.model('student', student);
//进行模块对象导出
module.exports = studentEntity;
创建路由 router
根据路由功能来进行请求路径的分发,我们如果去进行路由的编写比较的繁琐,这里利用到一个第三方的库,来帮我们做路由的分发 router
-
1.下载对应的第三方模块
npm install router
-
2.通过 require来进行模块的引入
const getRouter = require('router');
-
3.通过
getRouter()
方法获取路由对象const router = getRouter();
-
4.在我们监听的请求函数里面开启路由功能
server.on('request', (req, res) => { //第三个参数必须要带上 router(req,res,()=>{ //这个函数是我们路由分发完毕后,再会调用此函数 }); });
-
5.进行代码编写,第三方库里面帮我们定义好了 get方式请求的处理和post方式请求的处理
router.get('/index', (req, res) => { console.log('index 请求成功'); res.end('index 请求成功'); }) router.get('/list', (req, res) => { console.log('list 请求成功'); res.end('list 请求成功'); })
当用户属于 xxx/add
的时候,让给用户显示用户添加的页面,我们需要把模板页面copy到我们的工程目录下,注意:html页面放在views目录下,css要放在 public的css目录下,然后在路由中,用模板引擎 template 来进行渲染
//1.引入 router 模块
const getRouter = require('router');
//2.获取路由对象
const router = getRouter();
//5.引入 art-template模块
const template = require('art-template');
//6.引入 path
const path = require('path');
//设置根路径
template.defaults.root = path.join(__dirname, 'views');
//4.当用户输入了add路径,我们让用户看到添加用户的界面
router.get('/add', (req, res) => {
let html = template('index.html', {});
res.end(html);
});
router.get('/list', (req, res) => {
let html = template('list.html', {});
res.end(html);
});
server.on('request', (req, res) => {
//3.开启路由
router(req, res, () => {
console.log('请求过来了');
});
});
使用静态资源第三方库 serve-static
此时还没有完成,因为在html里面进行了css的引入,这里我们需要需要把一些静态资源引入进来,我们可以通过第三方模块来实现 serve-static
- 1.下载第三方模块
npm install serve-static
- 2.引入serve-static模块获取创建静态资源服务功能的方法
- 3.调用方法创建静态资源服务并指定静态资源服务目录
- 4.启用静态资源服务功能
//1.引入静态资源加载的模块
const serveStatic = require('serve-static');
//2.得到静态资源加载对象 传递静态资源的路径,方便后续使用
const static = serveStatic(path.join(__dirname, 'public'));
server.on('request', (req, res) => {
...
//3.开启静态资源
static(req, res, () => {});
});
编写用户添加的接口
修改add.html(add.art) 文件里面 form表单的请求路径跟请求方法(路径:/add,请求方法:post)
//引入 querystring模块,进行数据的解析
const querystring = require('querystring');
//用户提交数据的处理
router.post('/add', (req, res) => {
let data = '';
//正在接收数据
req.on('data', params => {
data += params;
})
//当数据接收完毕
req.on('end', () => {
let studentParams = querystring.parse(data);
student.create(studentParams);
});
//插入成功后进行重定向
res.writeHead(301, {
'Location': '/list'
})
//响应请求
res.end();
});
编写用户列表的接口
在 list.html(list.art)模板中,编写输出语句,利用标准语法就好
{{each students}}
<tr>
<th>{{$value.name}}</th>
<th>{{$value.age}}</th>
<th>{{$value.sex == '0' ? '男' : '女'}}</th>
<th>{{$value.email}}</th>
<th>
{{each $value.hobbies}}
<span>{{$value}}</span>
{{/each}}
</th>
<th>{{$value.collage}}</th>
<th>{{dateFormat($value.date, 'yyyy-mm-dd')}}</th>
</tr>
{{/each}}
在list的路由分发的函数里面,进行查询所有学生信息,然后通过模板引擎进行渲染
//引入 时间格式化 模板引擎
const dateFormat = requre('dateformat');
//给模板引擎配置其他模块
template.defaults.imports.dateFormat = dateFormat;
//这里我利用的是 异步的 async 跟 await 来实现,也可以通过 Promise的.then().catch() 来实现
router.get('/list', async(req, res) => {
//查询数据库里面所有学生信息
let students = await student.find();
let html = template('list.html', { students: students });
res.end(html);
});