zoukankan      html  css  js  c++  java
  • 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里的三个标签都引入,实现子模板的分离
    {{include,'子模板路径,相对路径’}}

    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中的一些测试接口的截图

  • 相关阅读:
    关于数组的练习题:
    函数(手写)
    常用函数和方法集
    用户输入年,月,日,计算该日是该年的第几天?需要考虑2月份的问题
    [备用] 你会在C#的类库中添加web service引用吗?
    [备用]权限设计方案、如何使用session、MVC如何使用模板、DropdownList、怎么添加Bootstrape框架、使用ASP.NET MVC 4 Bootstrap Layout Template(VS2012)
    [转:Pro ASP.NET MVC 5中的例子]使用MVC4,Ninject,EF,Moq,构建一个真实的应用电子商务SportsStore
    莫名其妙
    [备用] VS中生成报表
    [备用] 百度地图兴趣点抓取
  • 原文地址:https://www.cnblogs.com/BM-laoli/p/12673674.html
Copyright © 2011-2022 走看看