node.js之模板引擎artTemplate

什么是模板引擎

模板引擎是第三方模块。让开发者以更加友好的方式拼接字符串,使项目代码更加清晰、更加易于维护。

模板引擎使用步骤:

1,在命令行工具中使用 npm install art-template 命令进行下载

2,使用const template = require('art-template')引入模板引擎

3,告诉模板引擎要拼接的数据和模板在哪 const html = template(‘模板路径’, 数据);

4,使用模板语法告诉模板引擎,模板与数据应该如何进行拼接

 1 // 导入模板引擎
 2 // 返回的template是一个方法
 3 const template = require("art-template");
 4 
 5 // 导入路径拼接方法
 6 const path = require("path");
 7 // 拼接路径
 8 const views = path.join(__dirname,"views","index.art");
 9 
10 // template 方法是用来拼接字符串的
11 // 参数1:模板的路径   绝对路径。绝对路径最后一个为文件名。文件名的后缀要为.art
12 // 参数2:对象,即要在模板中显示的数据
13 // 返回值:拼接好的字符串
14 const html = template(views,{
15     name:"张三",
16     age:20
17 });
18 
19 console.log(html);
20 
21 
22 ------------------------------------------------------------
23 // 使用模板引擎就要有模板,并且模板的后缀名为 .art
24 // 模板代码:在模板代码可以使用模板引擎中传过来的数据
25 
26 <!doctype html>
27 <html lang="en">
28 <head>
29     <meta charset="UTF-8">
30     <title>Document</title>
31 </head>
32 <body>
33 
34 {{name}}
35 
36 {{age}}
37 
38 
39 </body>
40 </html>
模板引擎的示例

模板语法

模板引擎的语法,主要都是讲的在模板中使用这些语法,可以让template(‘模板路径’, 数据);中的数据在模板中运用。

art-template同时支持两种模板语法:标准语法原始语法

标准语法可以让模板更容易读写,原始语法具有强大的逻辑处理能力。

标准语法: {{ 数据 }}    原始语法:<%=数据  %>

输出

输出语法

标准语法:{{ 数据 }}

原始语法:<%=数据 %>

 1 <!doctype html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <meta name="viewport"
 6           content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
 7     <meta http-equiv="X-UA-Compatible" content="ie=edge">
 8     <title>Document</title>
 9 </head>
10 <body>
11 
12 <!-- 标准语法 -->
13 <p>{{ name }}</p>
14 <p>{{1+1}}</p>
15 <p>{{ 1+1 == 2 ? "相等":"不相等"}}</p>
16 
17 
18 <!-- 原始语法 -->
19 <p><%=name%></p>
20 <p><%=1+1%></p>
21 <p><%=1+1 ==2 ?"相等":"不相等"%></p>
22 
23 </body>
24 </html>
标准语法和原始语法的输出
 1 // 导入模板引擎
 2 // 返回的template是一个方法
 3 const template = require("art-template");
 4 // 用于拼接路径
 5 const path = require("path");
 6 
 7 const views = path.join(__dirname,"views","01.art");
 8 // template 方法是用来拼接字符串的
 9 // 参数1:模板的路径   绝对路径。绝对路径最后一个为文件名。文件名的后缀要为.art
10 // 参数2:对象,即要在模板中显示的数据
11 // 返回值:拼接好的字符串
12 const html = template(views,{
13     name:"张三",
14     age:20,
15 });
16 
17 console.log(html);
18 
19 /*
20 输出结果
21 
22 <body>
23 <!-- 标准语法 -->
24 
25 <p>张三</p>
26 <p>2</p>
27 <p>相等</p>
28 
29 <!-- 原始语法 -->
30 <p>张三</p>
31 <p>2</p>
32 <p>相等</p>
33 </body>
34 */
template方法传递数据和输出结果

注意:模板引擎中的数据,可以是template方法中传过来的数据,也可以是算数运算符,还可以是三元运算符。

原文输出

原文输出:如果我们想传递HTML代码,那么模板引擎并不会将HTML代码中的特殊符号进行解码,还是以编码的形式显示。

例如:<h1> 在模板中最后显示为  &#60;h1&#62;

那么我们就需要让这些特殊符号在模板中原文显示。

原文显示的语法:

标准语法:{{@ 数据 }}

原始语法:<% - 数据 %>

 1 <!doctype html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <meta name="viewport"
 6           content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
 7     <meta http-equiv="X-UA-Compatible" content="ie=edge">
 8     <title>Document</title>
 9 </head>
10 <body>
11 
12 <!-- 标准语法 -->
13 <p>{{content}}</p>
14 <p>{{@content}}</p>
15 
16 <!-- 原始语法 -->
17 <p><%=content%></p>
18 <p><%-content%></p>
19 
20 </body>
21 </html>
原文显示模板
 1 // 导入模板引擎
 2 // 返回的template是一个方法
 3 const template = require("art-template");
 4 
 5 const path = require("path");
 6 
 7 const views = path.join(__dirname,"views","01.art");
 8 // template 方法是用来拼接字符串的
 9 // 参数1:模板的路径   绝对路径。绝对路径最后一个为文件名。文件名的后缀要为.art
10 // 参数2:对象,即要在模板中显示的数据
11 // 返回值:拼接好的字符串
12 const html = template(views,{
13     content:"<h1>我是标签</h1>"
14 });
15 
16 console.log(html);
17 
18 /*
19 输出
20 <body>
21 
22 <!-- 标准语法 -->
23 <p>&#60;h1&#62;我是标签&#60;/h1&#62;</p>
24 <p><h1>我是标签</h1></p>
25 
26 <!-- 原始语法 -->
27 <p>&#60;h1&#62;我是标签&#60;/h1&#62;</p>
28 <p><h1>我是标签</h1></p>
29 
30 </body>
31 */
输出结果

条件判断

1  <!-- 标准语法 --> 
2  {{if 条件}} ... {{/if}}
3  {{if v1}} ... {{else if v2}} ... {{/if}}
4 
5  <!-- 原始语法 -->
6  <% if (value) { %> ... <% } %>
7  <% if (v1) { %> ... <% } else if (v2) { %> ... <% } %>
 1 // 标准语法
 2 {{if age>18}}
 3 年龄大于18
 4 {{else if age<15}}
 5 年龄小于15
 6 {{else}}
 7 年龄不符合要求
 8 {{/if}}
 9 
10 
11 // 原始语法
12 <%if(age > 18) {%>
13 年龄大于18
14 <% }%>
15 
16 // 原始语法
17 <%if (age >18){%>
18 年龄大于18
19 <%}else if(age > 15){%>
20 年龄大于15
21 <%} else {%>
22 年龄不符合要求
23 <%}%>
模板文件
 1 // 导入模板引擎
 2 // 返回的template是一个方法
 3 const template = require("art-template");
 4 
 5 const path = require("path");
 6 
 7 const views = path.join(__dirname,"views","02.art");
 8 // template 方法是用来拼接字符串的
 9 // 参数1:模板的路径   绝对路径。绝对路径最后一个为文件名。文件名的后缀要为.art
10 // 参数2:对象,即要在模板中显示的数据
11 // 返回值:拼接好的字符串
12 const html = template(views,{
13     name:"张三",
14     age:20
15 });
16 
17 console.log(html);
View Code

数据循环

 1  <!-- 标准语法 -->
 2  {{each target}}
 3      {{$index}} {{$value}}
 4  {{/each}}
 5 
 6 
 7   <!-- 原始语法 -->
 8  <% for(var i = 0; i < target.length; i++){ %>
 9      <%= i %> <%= target[i] %>
10  <% } %>
 1 <ul>
 2     {{each users}}
 3         <li>
 4             {{$value.name}}
 5             {{$value.age}}
 6             {{$value.sex}}
 7         </li>
 8     {{/each}}
 9 </ul>
10 
11 
12 <ul>
13 <% for (var i = 0;i<users.length;i++) {%>
14     <li>
15         <%= users[i].name%>
16         <%= users[i].age%>
17         <%= users[i].sex%>
18     <li>
19 <%}%>
20 </ul>
模板文件
 1 // 导入模板引擎
 2 // 返回的template是一个方法
 3 const template = require("art-template");
 4 
 5 const path = require("path");
 6 
 7 const views = path.join(__dirname,"views","03.art");
 8 // template 方法是用来拼接字符串的
 9 // 参数1:模板的路径   绝对路径。绝对路径最后一个为文件名。文件名的后缀要为.art
10 // 参数2:对象,即要在模板中显示的数据
11 // 返回值:拼接好的字符串
12 const html = template(views,{
13     users:[
14         {
15             name:"张三",
16             age:20,
17             sex:"男"
18         },
19         {
20             name:"李四",
21             age:30,
22             sex:"男"
23         },
24         {
25             name:"王五",
26             age:40,
27             sex:"女"
28         },
29         {
30             name:"赵六",
31             age:20,
32             sex:"女"
33         }
34     ]
35 });
36 
37 console.log(html);
38 
39 /*
40 
41 <ul>
42     
43         <li>
44             张三
45             20
46 47         </li>
48     
49         <li>
50             李四
51             30
52 53         </li>
54     
55         <li>
56             王五
57             40
58 59         </li>
60     
61         <li>
62             赵六
63             20
64 65         </li>
66     
67 </ul>
68 
69 
70 <ul>
71 
72     <li>
73         张三
74         20
75 76     <li>
77 
78     <li>
79         李四
80         30
81 82     <li>
83 
84     <li>
85         王五
86         40
87 88     <li>
89 
90     <li>
91         赵六
92         20
93 94     <li>
95 
96 </ul> 
97 
98 */
文件输出结果

子模板

子模板的作用:可以将网站公共区块(头部、底部)抽离到单独的文件中,在使用子模板语法将这些公共的文件引入即可。

1   <!-- 标准语法 -->
2  {{include '模板路径'}}
3 
4   <!-- 原始语法 -->
5  <% include('模板路径') %>
1 // 标准语法
2 {{ include './common/header.art'}}
3 // 原始语法
4 <% include('./common/header.art')%>
5 <div>{{msg}}</div>
6 // 原始语法
7 <% include('./common/footer.art')%>
8 // 标准语法
9 {{ include './common/footer.art'}}
模板代码
 1 // 导入模板引擎
 2 // 返回的template是一个方法
 3 const template = require("art-template");
 4 
 5 const path = require("path");
 6 
 7 const views = path.join(__dirname,"views","04.art");
 8 // template 方法是用来拼接字符串的
 9 // 参数1:模板的路径   绝对路径。绝对路径最后一个为文件名。文件名的后缀要为.art
10 // 参数2:对象,即要在模板中显示的数据
11 // 返回值:拼接好的字符串
12 const html = template(views,{
13     msg:"我是首页"
14 });
15 
16 console.log(html);
17 
18 
19 /*
20 *
21  输出结果
22 我是头部
23 
24 <div>我是首页</div>
25 
26 我是底部
27 * */
输出代码

模板继承

使用模板继承可以将网站HTML骨架抽离到单独的文件中,其他页面模板可以继承骨架文件。

 1  <!doctype html>
 2  <html>
 3      <head>
 4          <meta charset="utf-8">
 5          <title>HTML骨架模板</title>
 6         // 留下坑让继承的代码去填写
 7          {{block 'head'}}{{/block}}
 8      </head>
 9      <body>
10         // 留下坑让继承的代码填写
11          {{block 'content'}}{{/block}}
12      </body>
13  </html>
14 
15 --------------------------------------------------
16 // 继承代码,填写坑
17  {{extend './layout.art'}}// 继承的代码
18  {{block 'head'}} <link rel="stylesheet" href="custom.css"> {{/block}}
19  {{block 'content'}} <p>This is just an awesome page.</p> {{/block}}
 1 // 父模板
 2 <!doctype html>
 3 <html lang="en">
 4 <head>
 5     <meta charset="UTF-8">
 6     <title>Document</title>
 7     {{block "link"}} {{/block}}
 8 </head>
 9 <body>
10 {{block "content"}} {{/block}}
11 </body>
12 </html>
13 
14 ----------------------------------------------
15 // 子模板,用来继承父模板
16 {{extend './common/layout.art'}}
17 
18 {{block 'content'}}
19 <p>{{ msg }}</p>
20 {{/block}}
21 
22 {{block 'link'}}
23 <link rel="stylesheet" type="text/css" href="./main.css">
24 {{/block}}
模板继承代码语法示例
 1 // 导入模板引擎
 2 // 返回的template是一个方法
 3 const template = require("art-template");
 4 
 5 const path = require("path");
 6 
 7 
 8 const views = path.join(__dirname,"views","05.art");
 9 // template 方法是用来拼接字符串的
10 // 参数1:模板的路径   绝对路径。绝对路径最后一个为文件名。文件名的后缀要为.art
11 // 参数2:对象,即要在模板中显示的数据
12 // 返回值:拼接好的字符串
13 const html = template(views,{
14     msg:"我是首页"
15 });
16 
17 console.log(html);
输出示例

模板配置

模板配置可以让代码的使用变得简单。并且可以向模板中导入一些方法,和变量在模板中使用。

1,向模板中导入变量 template.defaults.imports.变量名 = 变量值;// 还可以是将一些方法导入到模板中使用

2,设置模板根目录 template.defaults.root = 模板目录;

3,设置模板默认后缀 template.defaults.extname = '.art'

 1 // 模板
 2 {{ format('yyyy-MM-dd',time)}}
 3 
 4 
 5 ----------------------------------------------------------
 6 // 配置语法和导入语法
 7 const template = require('art-template');
 8 const path = require('path');
 9 
10 // 第三方用于处理时间的模块
11 const format = require('date-format');
12 // 设置模板的根目录
13 template.defaults.root = path.join(__dirname, 'views');
14 
15 // 导入模板变量(方法)
16 template.defaults.imports.format = format;
17 
18 // 配置模板的默认后缀
19 template.defaults.extname = ".art";
20 
21 const html = template('06', {
22     time: new Date()
23 });
24 
25 console.log(html);
配置语法代码

综合案例

实现功能:

1,建立项目文件夹并生成项目描述文件

2,创建网站服务器实现客户端和服务器端通信

3,连接数据库并根据需求设计学员信息表

4,创建路由并实现页面模板呈递

5,实现静态资源访问

6,实现学生信息添加功能

7,实现学生信息展示功能

第一步:建立项目文件夹并生成项目描述文件

在students文件夹中创建model文件夹,用来存放有关数据库的代码

在students文件夹中创建public文件夹,用来存放静态资源相关的代码

在students文件夹中创建views文件夹,用来存放模板的文件(.art文件里面是HTML代码)

package.json 文件中存放项目描述信息

第二步:创建网站服务器实现客户端和服务器端通信

 1 // 引入http模块
 2 const http = require("http");
 3 
 4 // 创建服务
 5 const app = http.createServer();
 6 
 7 // 添加请求事件
 8 app.on("request", (req, res) => {
 9     // req为请求对象,res为响应对象
10     res.edn("OK");
11 });
12 
13 app.listen(80);
14 console.log("服务器开启成功");
View Code

第三步:连接数据库并根据需求设计学员信息表

 1 // 引入数据库模块
 2 const mongoose = require("mongoose");
 3 // 连接数据库
 4 mongoose.connect("mongodb://localhost/playground",{ useUnifiedTopology: true,useNewUrlParser: true})
 5     .then(()=>console.log("数据库连接成功"))
 6     .catch(()=>console.log("连接失败"));
 7 
 8 ---------------------------------------------------------------
 9 const mongoose = require("mongoose");
10 
11 // 创建学生的集合规则
12 const studentsSchema = new mongoose.Schema({
13     name:{
14         type:String,
15         require:true,
16         minlength:2,
17         maxlength:10
18     },
19     age:{
20         type: Number,
21         min:10,
22         max:25,
23     },
24     sex:{
25         type:String,
26     },
27     email:String,
28     hobbies:[String],
29     collage:String,
30     enterDate:{
31         type:Date,
32         default:Date.now()
33     }
34 });
35 
36 // 使用集合规则创建集合
37 const Student = mongoose.model("Student",studentsSchema);
38 
39 // 将学生信息集合进行导出
40 module.exports = Student;
41 
42 
43 ---------------------------------------------------------------------
44 // 引入http模块
45 const http = require("http");
46 // querystring 模块
47 const querystring = require("querystring");
48 // 导入连接数据库模块
49 require("./model/connect");
50 // 导入学生集合规则构造函数
51 const Student = require("./model/user");
52 // 创建服务
53 const app = http.createServer();
54 // 添加请求事件
55 app.on("request", (req, res) => {
56     // req 为请求参数。res为响应参数
57     res.end("OK");
58 });
59 
60 app.listen(80);
61 console.log("服务器开启成功");
View Code

第四步:创建路由并实现页面模板呈递

使用第三方模块router来实现路由,不在自己写路由

功能:实现路由

使用步骤:

1,获取路由对象

2,调用路由对象提供的方法创建路由

3,启用路由,使路由生效

 1 // 1,导入第三方模块
 2 const getRouter = require('router')
 3 // 2,获取路由对象
 4 const router = getRouter();
 5 // 3,调用路由对象提供的方法创建路由
 6 router.get('/add', (req, res) => {
 7     res.end('Hello World!')
 8 })
 9 // 启用路由,在事件请求对象中
10 server.on('request', (req, res) => {
11     // 参数1、参数2都为事件请求对象中的参数。参数3位回调函数并且为必选参数,这里不用先写一个空函数
12     router(req, res,()=>{})
13 })
第三方模块router的使用步骤

第五步:实现静态资源访问

使用第三方模块 serve-static。实现静态资源访问服务

步骤:

1,引入serve-static模块获取创建静态资源服务功能的方法

2,调用方法创建静态资源服务并指定静态资源服务目录

3,启用静态资源服务功能

1 // 引入第三方模块,返回的是一个方法
2 const serveStatic = require('serve-static')
3 // 调用该方法创建静态访问。指定静态资源所在文件夹
4 const serve = serveStatic('public')
5 server.on('request', () => { 
6 // 开启静态资源访问功能,req,res参数都为事件请求对象的参数。第三个参数为回调函数,必填参数,现在不需要使用,传递一个空函数
7     serve(req, res,()=>{});
8 })
9 server.listen(3000)
View Code

第六步:实现学生信息添加功能

实现步骤:

1,在模板的表单中指定请求地址与请求方式

2,为每一个表单项添加name属性

3,添加实现学生信息功能路由

4,接收客户端传递过来的学生信息

5,将学生信息添加到数据库中

6,将页面重定向到学生信息列表页面

 

第七步:实现学生信息展示功能

实现步骤:

1,从数据库中将所有的学生信息查询出来

2,通过模板引擎将学生信息和HTML模板进行拼接

3,将拼接好的HTML模板响应给客户端

 

 

 

--------------------------

 

--------------------------

 

  1 // 引入数据库模块
  2 const mongoose = require("mongoose");
  3 // 连接数据库
  4 mongoose.connect("mongodb://localhost/playground",{ useUnifiedTopology: true,useNewUrlParser: true})
  5     .then(()=>console.log("数据库连接成功"))
  6     .catch(()=>console.log("连接失败"));
  7 
  8 ---------------------------------------------------------------
  9 const mongoose = require("mongoose");
 10 
 11 // 创建学生的集合规则
 12 const studentsSchema = new mongoose.Schema({
 13     name:{
 14         type:String,
 15         require:true,
 16         minlength:2,
 17         maxlength:10
 18     },
 19     age:{
 20         type: Number,
 21         min:10,
 22         max:25,
 23     },
 24     sex:{
 25         type:String,
 26     },
 27     email:String,
 28     hobbies:[String],
 29     collage:String,
 30     enterDate:{
 31         type:Date,
 32         default:Date.now()
 33     }
 34 });
 35 
 36 // 使用集合规则创建集合
 37 const Student = mongoose.model("Student",studentsSchema);
 38 
 39 // 将学生信息集合进行导出
 40 module.exports = Student;
 41 
 42 
 43 ---------------------------------------------------------------------
 44 // 引入http模块
 45 const http = require("http");
 46 // 引入router模块
 47 const getRouter = require("router");
 48 // 引入path模块
 49 const path = require("path");
 50 // 引用静态资源访问模块
 51 const serveStatic = require("serve-static");
 52 // 引入模板引擎
 53 const template = require("art-template");
 54 // 获取路由对象
 55 const router = getRouter();
 56 // 实现静态资源访问
 57 const serve = serveStatic(path.join(__dirname, "public"));
 58 // querystring 模块
 59 const querystring = require("querystring");
 60 // 处理日期模块
 61 const dateformat = require("dateformat");
 62 
 63 // 导入到模板中dateformat方法
 64 template.defaults.imports.dateformat= dateformat;
 65 
 66 // 配置模板的根目录
 67 template.defaults.root = path.join(__dirname, "views");
 68 
 69 
 70 // 创建路由
 71 // 呈递学生档案信息页面
 72 router.get("/add", (req, res) => {
 73     let html = template("index.art", {});
 74 
 75     res.end(html);
 76 });
 77 
 78 // 呈递学生档案信息列表页面
 79 router.get("/list", async (req, res) => {
 80     // 查询学生信息
 81     let students = await Student.find();
 82     console.log(students);
 83     let html = template("list.art", {
 84         students:students
 85     });
 86 
 87     res.end(html);
 88 });
 89 // 路由:实现post请求的 /add 路由
 90 router.post("/add",(req,res)=>{
 91     // 接收post请求参数
 92     let formData = "";
 93 
 94     req.on("data",param =>{
 95         formData += param;
 96     });
 97 
 98     req.on("end",async ()=>{
 99        await Student.create(querystring.parse(formData));
100 
101        res.writeHead(301,{
102            Location:"/list"
103        });
104        res.end();
105     });
106 });
107 
108 // 导入连接数据库代码
109 require("./model/connect");
110 // 导入集合构造函数代码
111 const Student = require("./model/user");
112 // 创建服务器
113 const app = http.createServer();
114 // 为服务器添加请求事件
115 app.on("request", (req, res) => {
116     // 启用路由
117     router(req, res, () => {
118     });
119 
120     // 启用静态资源访问功能
121     serve(req, res, () => {
122     });
123 });
124 
125 app.listen(80);
126 console.log("服务器开启成功");
功能实现代码

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

------------

posted @ 2020-04-09 12:28  YKKY  阅读(726)  评论(0编辑  收藏  举报