【js模板引擎】萌新也能看懂的模板引擎

2024-03-05 08:59

本文主要是介绍【js模板引擎】萌新也能看懂的模板引擎,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

从一个实际需求出发认识模板引擎
实现一个模板引擎的思路及步骤

从一个实际需求出发认识模板引擎

当我们需要用js渲染一个歌曲列表的时候,由于数据需要向后端请求,所以实现不能在html中把数据写死。
如下所示,我们需要在页面上展示这样一个列表,

展示列表

但是却不能像下面一样把数据写死在li标签中。
这里写图片描述

这个时候有两种我们容易思考得到的方法来解决这个问题,一个是html字符串拼接,另一种是构建DOM对象。
第一种:HTML字符串拼接
这里写图片描述
第二种:构建DOM对象
这里写图片描述

但是这两种方法都有很大缺陷:
第一种方法容易漏引号,出现拼接错误。
第二种方法则是代码量增加,虽然可以用jquery来减少代码量,但依然不是最优选择。
这两种方法的共同特征都是需要创建一个li标签,然后里面的内容动态获取

var li =  '<li>'+ songs[i].name +'-'+songs[i].singer'</li>'

在这里我们可以使用一种更好的办法,

var li = stringFormat('<li>{0} - {1}</li>', songs[0].name, songs[0].singer)

构建一个stringFormat函数,向里面传入参数,第一参数是模板,{0},{1}会被后面传入的两个参数替换,这样当函数执行后返回的就是一个字符串

"<li>Some Like It Hot!!  - SPYAIR</li>"

这个stringFormat函数可以说,就是一个最为粗略的模板引擎了。
传入的参数:

'<li>{0} - {1}</li>'

就是一个模板,所谓的模板引擎就是能够解析含有特殊字符的逻辑代码,简化字符串拼接前端渲染小插件。

但是这样的话,就必须把这部分函数写在script标签中,否则无法区分哪部分是html代码,哪部分是逻辑代码,所以我们需要特殊的字符来表示,这个特殊的字符就是定界符,
比如这个模板,使用的定界符就是<%%>:

'<p>Hello, my name is <%name%>. I\'m <%age%> years old.</p>';

实现一个模板引擎的思路及步骤:

以上举例的模板还并不算复杂,当我们遇到下面这个模板的时候,情况就会变得不同。

var template = 
'My skills:' + 
'<%if(this.showSkills) {%>' +'<%for(var index in this.skills) {%>' + '<a href="#"><%this.skills[index]%></a>' +'<%}%>' +
'<%} else {%>' +'<p>none</p>' +
'<%}%>';
var data = {skills: ["js", "html", "css"],showSkills: true
}
var TemplateEngine = function(template, data) {return string
} 

现在需要理清楚我们的思路,我们拿到一个模板,需要让它里面有定界符包裹的代码能够像js代码一样运行,最后返回给我们一个包含了运行结果的字符串,我们现在需要的就是实现
1. 创建一个新数组,将没有定界符包裹的代码部分放入数组中
2. 分辨出js逻辑部分,也就是有定界符包裹的部分,取出,
3. 传入data
这样最后返回给我们的就是这样一个字符串,

这里写图片描述
最终代码如下:

var TemplateEngine = function(html, options) {var re = /<%([^%>]+)?%>/g, reExp = /(^( )?(if|for|else|switch|case|break|{|}))(.*)?/g, code = 'var r=[];\n', cursor = 0;var add = function(line, js) {js? (code += line.match(reExp) ? line + '\n' : 'r.push(' + line + ');\n') :(code += line != '' ? 'r.push("' + line.replace(/"/g, '\\"') + '");\n' : '');return add;}while(match = re.exec(html)) {add(html.slice(cursor, match.index))(match[1], true);cursor = match.index + match[0].length;}add(html.substr(cursor, html.length - cursor));code += 'return r.join("");';return new Function(code.replace(/[\r\t\n]/g, '')).apply(options);
}

可能很多人看不懂这个最终版本,下面我将把这个复杂版本简单化,添加注释,以便于理解:

var TemplateEngine = function(html, options) {//正则匹配出<%%>包裹的逻辑代码部分var re = /<%([^%>]+)?%>/g;//正则匹配出含有if|for|else|switch|case|break|{|}等关键字var reExp = /(^( )?(if|for|else|switch|case|break|{|}))(.*)?/g;//声明一个字符串code,用来保存我们最终输出的结果var code = 'var r=[];\n';//设置一个游标,用来遍历完我们传入的整个模板字符串var cursor = 0;//声明一个add函数,用来判断是js脚本部分,还是需要添加到数组中的字符串部分var add = function(line, js) {if(js === true){if(line.match(reExp)){code = code +   line + '\n'}else{code = code +  'r.push(' + line + ');\n'}}else{if(line !== ''){code = code + 'r.push("' + line.replace(/"/g, '\\"') + '");\n'; //引号添加转义符}else{code = code + ''}}return add}while( match = re.exec(html) ) {var matchIdx = match.index;//使用re正则匹配,在模板字符串中匹配到的第一个部分的最后一个字符的下一个字符的下标var matchPart = html.slice(cursor,matchIdx);//从模板字符串中截取出下标从cursor,到matchIdx的部分add(matchPart);//只传了第一参数,lineadd(match[1], true); //第二个参数设为true的话,直接进入if(js===true)这个判断中cursor = match.index + match[0].length; //游标更新}var rest = html.substr(cursor, html.length - cursor);//匹配结束后,模板字符串中最后剩余的部分add(rest);//这一部分也需要进入add函数中判断code = code +  'return r.join("");';//最后添加返回语句code = code.replace(/[\r\t\n]/g, '');//去除code字符串中的制表符,回车符和换行符等,使代码看起来更加简洁return new Function(code).apply(options); //将code放入Function()函数中运行,并且将code中的变量作用域绑定到data上。
}

最终我们会获得这样一个字符串code,
这里写图片描述
利用JS给我们提供了构造函数的“类”,
这里写图片描述
可以运行code
注意
这里写图片描述
这里之所以会报错,是因为console.log中添加的双引号没有加上转义符(\),所以会报错

完结:
写完这篇博客断断续续差不多用了两天的时间,理解一个东西不难,但是怎么用文字说明白就很伤脑筋了,不过也算是前进了一小步啦。
参考博客

这篇关于【js模板引擎】萌新也能看懂的模板引擎的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/775965

相关文章

IDEA自动生成注释模板的配置教程

《IDEA自动生成注释模板的配置教程》本文介绍了如何在IntelliJIDEA中配置类和方法的注释模板,包括自动生成项目名称、包名、日期和时间等内容,以及如何定制参数和返回值的注释格式,需要的朋友可以... 目录项目场景配置方法类注释模板定义类开头的注释步骤类注释效果方法注释模板定义方法开头的注释步骤方法注

JS+HTML实现在线图片水印添加工具

《JS+HTML实现在线图片水印添加工具》在社交媒体和内容创作日益频繁的今天,如何保护原创内容、展示品牌身份成了一个不得不面对的问题,本文将实现一个完全基于HTML+CSS构建的现代化图片水印在线工具... 目录概述功能亮点使用方法技术解析延伸思考运行效果项目源码下载总结概述在社交媒体和内容创作日益频繁的

Node.js 数据库 CRUD 项目示例详解(完美解决方案)

《Node.js数据库CRUD项目示例详解(完美解决方案)》:本文主要介绍Node.js数据库CRUD项目示例详解(完美解决方案),本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考... 目录项目结构1. 初始化项目2. 配置数据库连接 (config/db.js)3. 创建模型 (models/

使用Node.js制作图片上传服务的详细教程

《使用Node.js制作图片上传服务的详细教程》在现代Web应用开发中,图片上传是一项常见且重要的功能,借助Node.js强大的生态系统,我们可以轻松搭建高效的图片上传服务,本文将深入探讨如何使用No... 目录准备工作搭建 Express 服务器配置 multer 进行图片上传处理图片上传请求完整代码示例

用js控制视频播放进度基本示例代码

《用js控制视频播放进度基本示例代码》写前端的时候,很多的时候是需要支持要网页视频播放的功能,下面这篇文章主要给大家介绍了关于用js控制视频播放进度的相关资料,文中通过代码介绍的非常详细,需要的朋友可... 目录前言html部分:JavaScript部分:注意:总结前言在javascript中控制视频播放

C++中函数模板与类模板的简单使用及区别介绍

《C++中函数模板与类模板的简单使用及区别介绍》这篇文章介绍了C++中的模板机制,包括函数模板和类模板的概念、语法和实际应用,函数模板通过类型参数实现泛型操作,而类模板允许创建可处理多种数据类型的类,... 目录一、函数模板定义语法真实示例二、类模板三、关键区别四、注意事项 ‌在C++中,模板是实现泛型编程

MySQL常见的存储引擎和区别说明

《MySQL常见的存储引擎和区别说明》MySQL支持多种存储引擎,如InnoDB、MyISAM、MEMORY、Archive、CSV和Blackhole,每种引擎有其特点和适用场景,选择存储引擎时需根... 目录mysql常见的存储引擎和区别说明1. InnoDB2. MyISAM3. MEMORY4. A

MySQL InnoDB引擎ibdata文件损坏/删除后使用frm和ibd文件恢复数据

《MySQLInnoDB引擎ibdata文件损坏/删除后使用frm和ibd文件恢复数据》mysql的ibdata文件被误删、被恶意修改,没有从库和备份数据的情况下的数据恢复,不能保证数据库所有表数据... 参考:mysql Innodb表空间卸载、迁移、装载的使用方法注意!此方法只适用于innodb_fi

Node.js net模块的使用示例

《Node.jsnet模块的使用示例》本文主要介绍了Node.jsnet模块的使用示例,net模块支持TCP通信,处理TCP连接和数据传输,具有一定的参考价值,感兴趣的可以了解一下... 目录简介引入 net 模块核心概念TCP (传输控制协议)Socket服务器TCP 服务器创建基本服务器服务器配置选项服

mac安装nvm(node.js)多版本管理实践步骤

《mac安装nvm(node.js)多版本管理实践步骤》:本文主要介绍mac安装nvm(node.js)多版本管理的相关资料,NVM是一个用于管理多个Node.js版本的命令行工具,它允许开发者在... 目录NVM功能简介MAC安装实践一、下载nvm二、安装nvm三、安装node.js总结NVM功能简介N