Node教程——模板引擎教程

模板引擎教程

其实这个玩意儿也是一个API一个工具,你学习之后知道怎么使用就完事,
其实这个也非常的鸡肋 ,因为所有的渲染都是在后台做的!!!非常非常小的项目,用这个就算了,大的项目还是老老实实写接口

我们发现总是去拼接字符串实在是太low了。于是乎我们这样来干,使用模板替代字符串拼接

模板引擎有很多,我们选一个art-template,这个是腾讯开发的,目前运行最快的,引擎是Node的第三方模块
你需要npm下载,然后与大多数的API使用一样,引入然后使用,

主要的使用,给数据 并且制定数据要怎么拼接

简单的使用

  • 流程如下
  1. 在命令行工具中使用 npm install art-template 命令进行下载

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

  3. 告诉模板引擎要拼接的数据和模板在哪 const html = template(‘模板路径’, 数据);返回的就是字符串
    注意:我们呢的引擎的文件是.art,但是文件的内容还是html格式了,路径是绝对路径

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

  • 代码实例

//需求我们把一个对象
const template = require('art-template');
const path = require('path');

const views = path.join(__dirname, 'views', '01.art');

//第二个参数就是在模板里面使用的数据
const html = template(views, {
    name: '张三',
    age: 20,
    content: '<h1>我是标题</h1>'
})

console.log(html);

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Document</title>
</head>
<body>
	<!-- 标准语法 -->
	<p>{{ name }}</p>
	<p>{{ 1 + 1 }}</p>
	<p>{{ 1 + 1 == 2 ? '相等' : '不相等' }}</p>
	<p>{{ content }}</p>//这个是原封不动的,不会解析成网页标签
	<p>{{@ content }}</p>//解析版
	
	<!-- 原始语法 -->
	<p><%= name %></p>
	<p><%= 1 + 2%></p>
	<p><%= 1 + 1 == 2 ? '相等' : '不相等' %></p>
	<p><%= content%></p>
	<p><%- content%></p>
</body>
</html>

语法详解:

语法有两种 原始语法 还有 标准语法,两个结合最好,原始的语法里面可以全部都丢js代码

  1. 大胡子 {

首先是我们的大胡子语法:{{ }} 这个里面的就是我们要输出的东西。其实你可以怎么理解:{{}}里面丢的就是js的代码,

代码实例,注意这里的数据还是上面的那个张三对象


<body>
	<!-- 标准语法 -->
	<p>{{ name }}</p>
	<p>{{ 1 + 1 }}</p>
	<p>{{ 1 + 1 == 2 ? '相等' : '不相等' }}</p>
	<p>{{ content }}</p>//这个是原封不动的,不会解析成网页标签
	<p>{{@ content }}</p>
	
	<!-- 原始语法 -->
	<p><%= name %></p>
	<p><%= 1 + 2%></p>
	<p><%= 1 + 1 == 2 ? '相等' : '不相等' %></p>
	<p><%= content%></p>
	<p><%- content%></p>
</body>

进行页面渲染

const template = require('art-template');
const path = require('path');

const views = path.join(__dirname, 'views', '01.art');

const html = template(views, {
    name: '张三',
    age: 20,
    content: '<h1>我是标题</h1>'
})

console.log(html);
  1. 条件判断

这个可以根据条件来渲染页面
你需要明白,这个里面的东西 基本上就是js就完事
基础的语法

if(){
    条件成立显示的内容(在这里里面渲染的就是我们html)
}

{{if age > 18}}
	年龄大于18
{{else if age < 15 }}
	年龄小于15
{{else}}
	年龄不符合要求
{{/if}}

<% if (age > 18) { %>
	年龄大于18
<% } else if (age < 15) { %>
	年龄小于15
<% } else { %>
	年龄不符合要求
<% } %>

进行页面渲染

const template = require('art-template');
const path = require('path');

const views = path.join(__dirname, 'views', '01.art');

const html = template(views, {
    name: '张三',
    age: 20,
    content: '<h1>我是标题</h1>'
})

console.log(html);
  1. 循环

你需要明白,我们拿的数据都是数组或者对象键值对,这种,那么循环渲染就非常重要

数据


onst template = require('art-template');
const path = require('path');

const views = path.join(__dirname, 'views', '03.art');
// 啧啧啧
const html = template(views, {
    users: [{
        name: '张三',
        age: 20,
        sex: '男'
    }, {
        name: '李四',
        age: 30,
        sex: '男'
    }, {
        name: '玛丽',
        age: 15,
        sex: '女'
    }]
});

console.log(html);

页面

<ul>
	{{each users}}//each //这不就是我们的forEach循环? 
		<li>
			{{$value.name}} //$value就是当前的循环项目,$index就是索引
			{{$value.age}}
            {{$value.sex}}
            {{ $index }}
		</li>
	{{/each}}
</ul>

<ul>
	<% for (var i = 0; i < users.length; i++) { %>
		<li>
			<%=users[i].name %>
			<%=users[i].age %>
			<%=users[i].sex %>
		</li>
	<% } %>
</ul>

  1. 子模板

说白了就把共同的东西抽离出去
需求:比如把这里,我有一个04页面,然后我需要把common里的三个标签都引入,实现子模板的分离

04页面结构

{{ include './common/header.art' }}
<% include('./common/header.art') %>
<div> {{ msg }} </div>
{{ include './common/footer.art' }}
<% include('./common/footer.art') %>  

footer部分

头部

header部分

底部

layout部分

布局
  1. 如何进行html结构抽离。模板继承

什么是继承?说的就是把更多的相同的东西头里出来,然后其它人都可以通过继承拿到这个公共部分

要记得在我们的基础模板里面挖坑,因为不同的页面是有不同的骨架内容的

实例代码,挖两个坑,父亲这个是我们首页的首页

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Document</title>
	{{block 'link'}} {{/block}} //这里的link是当前位置(就是你挖的坑的名字)你随便写,一个名字而已
</head>
<body>
	{{block 'content'}} {{/block}}
</body>
</html>

继承的模板,儿子
这就是我们的首页

{{extend './common/layout.art'}}
<!-- //继承模板 -->

<!-- //填坑 -->
{{block 'content'}}
<p>{{ msg }}</p>
{{/block}}

{{block 'link'}}
<link rel="stylesheet" type="text/css" href="./main.css">
{{/block}}

数据块

const template = require('art-template');
const path = require('path');

const views = path.join(__dirname, 'views', '04.art');

const html = template(views, {
    msg: '我是首页'
});

console.log(html);

  1. 配置一,导入变量

如何把数据中的日期进行格式化?
我们的方案,用一个方法 处理一下日期就完事了,但是??我们这个方法能不能丢给模板?
大难是可以的,用一个变量把方法的值接过来就完事,注意我们后续基本上使用管道pipe,对于初级程序员是使用这个东西,高级的就使用管道pipe

注意我们去找一个日期处理的工具
npm

使用的步骤:
向模板中导入变量 template.defaults.imports.变量名 = 变量值;
设置模板根目录 template.defaults.root = 模板目录
设置模板默认后缀 template.defaults.extname = '.art'

数据块

const template = require('art-template');
const path = require('path');
const dateFormat = require('dateformat');
// //拼命接路径
// const views = path.join(__dirname, 'views', '04.art');

// 设置模板的根目录,这样我们就不需要拼接路径了
template.defaults.root = path.join(__dirname, 'views');


// 导入模板变量
template.defaults.imports.dateFormat = dateFormat;

// 配置模板的默认后缀
template.defaults.extname = '.html';

const html = template('06.art', {
    time: new Date()
});

// 渲染模板 template 
// 不写后缀的时候07就会自己去找配置的html后缀
console.log(template('07', {}));
console.log(html);

模板

{{ dateFormat(time, 'yyyy-mm-dd')}} 

实战:添加学生档案

以下是项目的目标

注意:你要npm下载一些东西模板引擎啦两个第三方的包啊
重要的事情再说一遍,我们想用返回值的方式 获取异步api的结果,就需要用两个关键字async还有await,要不然你只能用promise.then来干活了,

  • 特别说明:
>我们将以一个全栈开发人员的角度去分析还有设计这个小demo,
>
>1.首先我们需要设计数据库
>
>2.其次我们需要设计后台API,也就是写接口
>
>3.最后我们需要作为一名前端开发人员调接口渲染数据

  1. 业务逻辑分析

    • 建立项目文件夹并生成项目描述文件。描述文件?就是那个pack.json
    • 创建网站服务器实现客户端和服务器端通信
    • 连接数据库并根据需求设计学员信息表
    • 创建路由并实现页面模板呈递
    • 实现静态资源访问
    • 实现学生信息添加功能
    • 实现学生信息展示功能
  2. 我们先来确定使用的技术栈
    知识点:http请求响应、数据库、模板引擎、静态资源访问。

  3. 构建文件夹结构

img

  1. 建立服务器,设计数据库

这里我们先把数据库模块化出去,然后使用是一个新的api路由api

  • common还有user的js
const mongoose = require('mongoose');
// 连接数据库
mongoose.connect('mongodb://localhost/playground', { useNewUrlParser: true })
    .then(() => console.log('数据库连接成功'))
    .catch(() => console.log('数据库连接失败'))

数据库设计

const mongoose = require('mongoose');
// 创建学生集合规则 设定字段,设计数据库
const studentsSchema = new mongoose.Schema({
    name: {
        type: String,//类型
        required: true,//是否必须
        minlength: 2,//最大最小长度等.....
        maxlength: 10
    },
    age: {
        type: Number,
        min: 10,
        max: 25
    },
    sex: {  
        type: String
    },
    email: String,
    hobbies: [String],
    collage: String,
    enterDate: {
        type: Date,
        default: Date.now
    }
});
// 创建学生信息集合
const Student = mongoose.model('Student', studentsSchema);
// 将学生信息集合进行导出
module.exports = Student;
  • 知识补充:静态资源访问serve-static
// 使用步骤
//     引入serve-static模块获取创建静态资源服务功能的方法
//     调用方法创建静态资源服务并指定静态资源服务目录
//     启用静态资源服务功能



const serveStatic = require('serve-static')
const serve = serveStatic('public')
server.on('request', () => { 
    serve(req, res)
})
server.listen(3000)

  • app.js
// 引入http模块
const http = require('http');
// 引入模板引擎
const template = require('art-template');
// 引入path模块
const path = require('path');
// 引入静态资源访问模块,拿来主义
const serveStatic = require('serve-static');
// 引入处理日期的第三方模块,实现路由功能的routme
const dateformat = require('dateformat');

const router = require('./route/index');





// 实现静态资源访问服务
const serve = serveStatic(path.join(__dirname, 'public'))

// 配置模板的根目录
template.defaults.root = path.join(__dirname, 'views');
// 处理日期格式的方法
template.defaults.imports.dateformat = dateformat;


// 数据库连接
require('./model/connect');

// 创建网站服务器 
const app = http.createServer();
// 当客户端访问服务器端的时候
app.on('request', (req, res) => {
    // 启用路由功能
    router(req, res, () => {})
        // 启用静态资源访问服务功能
    serve(req, res, () => {})
});
// 端口监听
app.listen(80);
console.log('服务器启动成功');

  • 路由的简要的语法

//步骤
//  1.获取路由对象
//  2.调用路由对象提供的方法创建路由
//  3.启用路由,使路由生效


const getRouter = require('router')
const router = getRouter();

router.get('/add', (req, res) => {
    res.end('Hello World!')
}) 

server.on('request', (req, res) => {
    router(req, res)
})


  • roter下的路由,业务处理,先测试接口,再渲染数据,注意我们的渲染都是在后台里面做的,并不是真正的写接口,这一点你需要明白
// 引入router模块//专门处理路由的一个第三方模块
const getRouter = require('router');
// 获取路由对象
const router = getRouter();
// 学生信息集合
const Student = require('../model/user');
// 引入模板引擎
const template = require('art-template');
// 引入querystring模块,你是否还接这个是什么?这个就是处理我们的post请求数据的!
const querystring = require('querystring');

// 呈递学生档案信息页面
router.get('/add', (req, res) => {
    let html = template('index.art', {});
    res.end(html);
})

// 呈递学生档案信息列表页面
router.get('/list', async(req, res) => {
        // 查询学生信息
        let students = await Student.find();
        console.log(students);

        let html = template('list.art', {
            students: students
        })

// res.end(students )//测试接口

res.end(html )
    })
    // 实现学生信息添加功能路由
router.post('/add', (req, res) => {
    // 接收post请求参数
    let formData = '';
    req.on('data', param => {
        formData += param;
    });
    req.on('end', async() => {
        await Student.create(querystring.parse(formData))
    
    res.writeHead(301, {
            Location: '/list'
        });
        
    // 测试接口
        res.end( 'ok' )
    })
});

module.exports = router;
  1. 渲染,我们其实是在服务器里面做的渲染,这里的耦合度太高了,后期我们会把前后台都分开

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>学员信息</title>
	<link rel="stylesheet" href="./css/list.css">
</head>
<body>
	<table>
		<caption>学员信息</caption>
		<tr>
			<th>姓名</th>
			<th>年龄</th>
			<th>性别</th>
			<th>邮箱地址</th>
			<th>爱好</th>
			<th>所属学院</th>
			<th>入学时间</th>
		</tr>
		{{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.enterDate, 'yyyy-mm-dd')}}</th>
			</tr>
		{{/each}}
		
	</table>
</body>
</html>

总结:
思路非常的重要,路由的get是在请求页面, post是在发数据
虽然我们没有前后台分离,但是我希望你能明白如何用Node写接口,这个技能还是蛮重要的!

关于接口的测试工具:postman,以下是我在这个小demo中的一些测试接口的截图

posted @ 2020-04-10 15:14  BM老李  阅读(572)  评论(0编辑  收藏  举报