【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

相关文章

LiteFlow轻量级工作流引擎使用示例详解

《LiteFlow轻量级工作流引擎使用示例详解》:本文主要介绍LiteFlow是一个灵活、简洁且轻量的工作流引擎,适合用于中小型项目和微服务架构中的流程编排,本文给大家介绍LiteFlow轻量级工... 目录1. LiteFlow 主要特点2. 工作流定义方式3. LiteFlow 流程示例4. LiteF

SpringBoot集成LiteFlow实现轻量级工作流引擎的详细过程

《SpringBoot集成LiteFlow实现轻量级工作流引擎的详细过程》LiteFlow是一款专注于逻辑驱动流程编排的轻量级框架,它以组件化方式快速构建和执行业务流程,有效解耦复杂业务逻辑,下面给大... 目录一、基础概念1.1 组件(Component)1.2 规则(Rule)1.3 上下文(Conte

Python基于微信OCR引擎实现高效图片文字识别

《Python基于微信OCR引擎实现高效图片文字识别》这篇文章主要为大家详细介绍了一款基于微信OCR引擎的图片文字识别桌面应用开发全过程,可以实现从图片拖拽识别到文字提取,感兴趣的小伙伴可以跟随小编一... 目录一、项目概述1.1 开发背景1.2 技术选型1.3 核心优势二、功能详解2.1 核心功能模块2.

MySQL 存储引擎 MyISAM详解(最新推荐)

《MySQL存储引擎MyISAM详解(最新推荐)》使用MyISAM存储引擎的表占用空间很小,但是由于使用表级锁定,所以限制了读/写操作的性能,通常用于中小型的Web应用和数据仓库配置中的只读或主要... 目录mysql 5.5 之前默认的存储引擎️‍一、MyISAM 存储引擎的特性️‍二、MyISAM 的主

使用Python获取JS加载的数据的多种实现方法

《使用Python获取JS加载的数据的多种实现方法》在当今的互联网时代,网页数据的动态加载已经成为一种常见的技术手段,许多现代网站通过JavaScript(JS)动态加载内容,这使得传统的静态网页爬取... 目录引言一、动态 网页与js加载数据的原理二、python爬取JS加载数据的方法(一)分析网络请求1

Java如何根据word模板导出数据

《Java如何根据word模板导出数据》这篇文章主要为大家详细介绍了Java如何实现根据word模板导出数据,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... pom.XML文件导入依赖 <dependency> <groupId>cn.afterturn</groupId>

VSCode中配置node.js的实现示例

《VSCode中配置node.js的实现示例》本文主要介绍了VSCode中配置node.js的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着... 目录一.node.js下载安装教程二.配置npm三.配置环境变量四.VSCode配置五.心得一.no

Python中Flask模板的使用与高级技巧详解

《Python中Flask模板的使用与高级技巧详解》在Web开发中,直接将HTML代码写在Python文件中会导致诸多问题,Flask内置了Jinja2模板引擎,完美解决了这些问题,下面我们就来看看F... 目录一、模板渲染基础1.1 为什么需要模板引擎1.2 第一个模板渲染示例1.3 模板渲染原理二、模板

利用Python打造一个Excel记账模板

《利用Python打造一个Excel记账模板》这篇文章主要为大家详细介绍了如何使用Python打造一个超实用的Excel记账模板,可以帮助大家高效管理财务,迈向财富自由之路,感兴趣的小伙伴快跟随小编一... 目录设置预算百分比超支标红预警记账模板功能介绍基础记账预算管理可视化分析摸鱼时间理财法碎片时间利用财

如何在 Spring Boot 中实现 FreeMarker 模板

《如何在SpringBoot中实现FreeMarker模板》FreeMarker是一种功能强大、轻量级的模板引擎,用于在Java应用中生成动态文本输出(如HTML、XML、邮件内容等),本文... 目录什么是 FreeMarker 模板?在 Spring Boot 中实现 FreeMarker 模板1. 环