art-template 模板引擎

@

目录


一、模板引擎的基础概念

1. 模板引擎

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

// 未使用模板引擎的写法
var ary = [{ name: '张三', age: 20 }];
var str = '<ul>';
for (var i = 0; i < ary.length; i++) {
str += '<li>\
<span>'+ ary[i].name +'</span>\
<span>'+ ary[i].age +'</span>\
</li>';
}
str += '</ul>';
<!-- 使用模板引擎的写法 -->
<ul>
{{each ary}}
<li>{{$value.name}}</li>
<li>{{$value.age}}</li>
{{/each}}
</ul>


2. art-template模板引擎

art-template (aui.github.io)



二、在NodeJS中使用art-template

① 基本使用步骤:

  1. 在命令行工具中使用 npm install art-template 命令进行下载
  2. 使用const template = require('art-template')引入模板引擎
  3. 告诉模板引擎要拼接的数据和模板在哪 const html = template(‘模板路径’, 数据);
  4. 使用模板语法告诉模板引擎,模板与数据应该如何进行拼接

vscode中默认不会把art文件视为html文件,这需要另外设置:参考博客

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Document</title>
</head>
<body>
	{{ name }}
	{{ age }}
</body>
</html>
//引入art-template模板,实际返回一个方法
const template = require('art-template');
const path = require('path');
const views = path.join(__dirname, 'views', '01.art');
/*
template(参数1, 参数2)
参数1: art模板文件路径(优先使用绝对路径)
参数2:art模板文件使用的数据, 对象类型
返回art模板文件字符串(html)
*/
const html = template(views, {
    name: '张三',
    age: 20,
})
console.log(html);

运行结果:

PS D:\...\template> node app.js
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    张三 20
</body>
</html>

②模板引擎的语法

art-template同时支持两种模板语法:标准语法原始语法
标准语法可以让模板更容易读写,原始语法具有强大的逻辑处理能力。


1. 输出

将某项数据输出在模板中,标准语法和原始语法如下:

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

在 输出 语法中,可以进行 变量 的输出、 对象属性 的输出、 三元表达式 输出、 逻辑或 输出、加减乘除等表达式 输出。

<!-- 标准语法 -->
<h2>{{value}}</h2>
<h2>{{a ? b : c}}</h2>
<h2>{{a + b}}</h2>
<!-- 原始语法 -->
<h2><%= value %></h2>
<h2><%= a ? b : c %></h2>
<h2><%= a + b %></h2>

2. 原文输出

如果要输出的 value 值中,包含了 HTML 标签结构,则需要使用原文输出语法,才能保证 HTML 标签被正常渲染。

默认模板引擎不会解析标签,会将其转义后输出。

标准原文输出语法:{{@ 数据 }}
原始原文输出语法:<%- 数据 %>

<!-- 标准语法 -->
<h2>{{@ value }}</h2>
<!-- 原始语法 -->
<h2><%- value %></h2>

3. 条件判断

<!-- 标准语法 -->
{{if 条件}} ... {{/if}}
{{if 条件1}} ... {{else if 条件2}} ... {{/if}}
<!-- 原始语法 -->
<% if (条件1) { %> 
... 
<% } else if (条件2) { %>
... 
<% } else { %>
...
<% } %>

注意:原始语法输出符内部支持原生js语法

4. 循环

标准语法:{{each 数据}} ... {{/each}}
原始语法:<% for() { %> ... <% } %>

<!-- 标准语法
each: 模板循环标识符
target: 要循环的数据
$index: 当前循环项的索引
$value: 当前循环项的值
-->
{{each target}}
{{$index}} {{$value}}
{{/each}}
<!-- 原始语法
原生js语法
-->
<% for(var i = 0; i < target.length; i++){ %>
<%= i %> <%= target[i] %>
<% } %>

5. 子模版

使用子模板可以将网站公共区块(比如头部、底部标签块)抽离到单独的文件中。
通过使用include子模板(公共模板) 引入到其他模板中

  • 标准语法:{{include '子模板相对路径'}},其中的include表示一个标识符
  • 原始语法:<%include('子模版相对路径模板') %>,其中的include表示一个方法
<!-- 标准语法 -->
{{include './header.art'}}
<!-- 原始语法 -->
<% include('./header.art') %>

include 引入子模版地址问题

	{{include './common/header.art'}}

模板文件中引入公共部分语法中的地址为相对路径,这个相对路径由模板引擎解析,是相对于当前模板文件的路径,而不是相对于当前请求地址路径


6. 模板继承

模板继承指的是其他模板可以继承一些公共模板,类似子模版,但使用模板继承可以将网站HTML骨架抽离到单独的文件中,其他页面模板可以继承骨架文件。
art-template 模板引擎
语法:
在其他模板中,使用{{extends '被继承模板的相对路径'}}去继承公共模板

模板继承可以根据当前模板的需要去指定被继承模板的一些部分

  • 在被继承模板中,使用{{block '预留空名'}}{{/block}}去设置预留空
  • 在其他模板中,使用{{block '预留空名'}} 指定内容... {{/block}}去填充预留孔

简单案例:

<!-- 公共骨架模板layout.art -->
<!doctype html>
<html>
	<head>
		<meta charset="utf-8">
		{{block 'title'}}{{/block}}
		{{block 'link'}}{{/block}}
</head>
<body>
{{block 'content'}}{{/block}}
</body>
</html>
<!--index.art 首页模板-->
{{extend './layout.art'}}
{{block 'title'}} <title>这是首页</title> {{/block}}
{{block 'link'}} <link rel="stylesheet" href="custom.css"> {{/block}}
{{block 'content'}} <p>This is just an awesome page.</p> {{/block}}

命令行输出

PS D:\...\template> node 05.js
<!doctype html>
<html>
        <head>
                <meta charset="utf-8">
                 <title>这是首页</title>
                 <link rel="stylesheet" href="custom.css">
</head>
<body>
 <p>This is just an awesome page.</p>
</body>
</html>
PS D:\...\test\template>

7. 模板配置

向模板中导入变量

/*
template: 当前js文件导入的 art-template 模板引擎模块
*/
template.defaults.imports.变量名 = 变量值;

语句执行过后便可在所链接的模板中使用该变量

dateformat

使用场景: 在模板中格式化日期数据
引用第三方模块:dateformat - npm

{{dateformat(time, 'yyyy-mm-dd')}}
const template = require('art-template');
const path = require('path');
const dateformat = require('dateformat');
const view = path.join(__dirname, 'views', '06.art');

//! 导入模板变量
template.defaults.imports.dateformat = dateformat;
const html = template(view , {
    time: new Date(),
});
console.log(html);

命令行输出

PS D:\...\template> node 06.js
2021-09-01

设置模板根目录

通过多个template()渲染多个模板,但每次都得手动设置模板地址

const view1 = path.join(__dirname, 'view', '01.art');
const view2 = path.join(__dirname, 'view', '02.art');
console.log(template(view1,{}));
console.log(template(view2,{}));

这样会造成代码冗余..

通过设置模板根目录,让每次调用template()渲染模板时只需要指定模板文件名,让模板引擎自动到模板根目录下寻找指定的模板文件

/*设置模板的根目录
template: 当前js文件导入的 art-template 模板引擎模块
*/
template.defaults.root = path.join(__dirname, 根目录名);

简单案例

const template = require('art-template');
// 设置模板的根目录
template.defaults.root = path.join(__dirname, 'views');
console.log(template('06.art', {
	msg: '06.art模板文件自动被找到并渲染'
}))

设置模板默认后缀

通过设置模板默认后缀名:

// 配置模板的默认后缀
//template: 当前js文件导入的 art-template 模板引擎模块
template.defaults.extname = '.html';

template()渲染模板时直接指定模板文件名(不需要后缀):

console.log(template('07', {
	msg: '模板引擎自动到模板根目录下寻找 "07.html" 模板文件并渲染'
}));

当然,如果指定了模板文件全名(包含后缀名),模板引擎也会自动到根目录寻找指定文件并渲染。


③ 模板文件外链资源请求地址问题

模板文件中的外链资源路径并不是相对于当前这个模板文件的路径,
而是的相对路径是相对于地址栏中的请求路径的。
比如
地址栏输入localhost/admin/login,服务器响应一个模板文件并通过引擎解析给浏览器

浏览器是如下解析路径的,它回去找 /admin 这个目录 下的 login 这个文件所以,最后部分其实是指定的文件而不是目录

login.art模板文件下的外链资源路径是相对于当前模板的请求路径/admin,比如

<link rel="stylesheet" href="css/base.css">

这个link标签实际发出的请求地址是:localhost/admin/css/base.css

假如此时我们把访问login.art的请求路径改变localhost/abc/login,这样模板文件正常访问,但是里面的外链资源依然是相对于/abc这个路径,然而此时的静态资源是存放在/admin下的,这时外链资源就会响应失败。

解决方法:把模板文件中的外链资源请求地址 通过'/' 改成 绝对路径,那么外链资源的请求地址就与当前浏览器的请求地址没关系了,如下

<link rel="stylesheet" href="/admin/css/base.css">

此时外链资源实际的请求地址是localhost/admin/css/base.css




三、在浏览器中使用art-template

① 基本使用步骤

  1. 下载 art-template-web.js 模板引擎库文件并在 HTML 页面中引入库文件
    <!--
    注意: 这里的路径要写绝对路径,不然会相对与url地址的路径, 
    如果url地址跟当html文件的地址不匹配就会报错
    -->
    <script src="/js/template-web.js"></script>
    
  2. 准备 art-template 模板
    在模板中支持基本模板语法,与在nodeJS中的模板基本语法一样。
    <!--
    id: id名,用来区分不同不同的模板
    type: 在<script>中需要指定html类型
    -->
    <script id="tpl" type="text/html">
    	<div class="box"></div>
    </script>
    
  3. 告诉模板引擎将哪一个模板和哪个数据进行拼接
    /*
    template: 模板库文件提供的方法
    parms1: 模板id名
    parms2: 传入模板的数据
    return: 根据模板,返回一串特定字符
    */
    var html = template('tpl', {username: 'zhangsan', age: '20'});
    
  4. 通过模板语法告诉模板引擎,数据和html字符串要如何拼接
    <script id="tpl" type="text/html">
    	<div class="box"> {{ username }} </div>
    </script>
    
  5. 将拼接好的html字符串添加到页面中
    
    document.getElementById('container').innerHTML = html;
    


② 过滤器

  • 简介
    过滤器是个函数,用来处理特殊值并返回想要的结果
graph LR A[需处理的值] -- 参数 --> B[过滤器函数] -- 返回值 --> C[输出新值]
  • 语法

    {{value | filterName}}
    

    过滤器语法类似 管道操作符,它的上一个输出作为下一个输入。
    定义过滤器的基本语法如下:

    template.defaults.imports.filterName = function(value){/*return处理的结果*/}
    

  • 举例
    定义一个 格式化时间 的过滤器 dateFormat 如下:
    	template.defaults.imports.dateFormat = function(date) {
    		var y = date.getFullYear()
    		var m = date.getMonth() + 1
    		var d = date.getDate()
    		return y + '-' + m + '-' + d // 注意,过滤器最后一定要 return 一个值
    	}
    	var html = template('tpl',{regTime: new Date()});
    	console.log(html);
    	/*
    	 <div>2021-10-2</div>
    	*/
    
    在模板中使用过滤器函数
    <script type="text/html" id="tpl">
    	<!--等效 <div>{{dateFormar(regTime)}}</div> -->
    	<div>注册时间:{{regTime | dateFormat}}</div>
    <script>	
    


② 实现自定义简易的模板引擎

说明

利用正则对字符串的操作,实现自定义模板函数

实现步骤

定义模板结构

<!-- 定义模板结构 -->
<script type="text/html" id="tpl-user">
	<div>姓名:{{ name }}</div>
	<div>年龄:{{ age }}</div>
	<div>性别:{{ gender }}</div>
	<div>住址:{{ address }}</div>
</script>

预调用模板引擎

//定义数据
var data = {name: '张三', age: 20, gender: '男', address: '深圳'}

//调用自定义模板函数
var htmlStr = template('tpl-user', data)

//渲染html解构
document.getElementById("user-box").innerHTML = htmlStr

封装 template 函数

//自定义模板函数 template.js
function template(id, data){
	var str = document.getElementById(id).innerHTML
	var pattern = /{{\s*([a-zA-Z]+)\s*}}/
	var patternResult = null
	while(patternResult = pattern.exec(str)){
		str = str.replace(patternResult[0], patternResult[1]);
	}
	return str;
}

exec()
replace()


④ 导入并使用自定义的模板引擎
如果自定义模板函数在其他文件中,也要导入即可

<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>自定义模板引擎</title>
<!-- 导入自定义的模板引擎 -->
<script src="./js/template.js"></script>
</head>

art-template 模板引擎

上一篇:云溪数据库选型ART树作为数据查找算法


下一篇:【20220128】 Markdown 笔记总结9 -- 支持对象