摘要:这是一个系列文章,将会介绍目前前端领域里用到的三种模板引擎技术,它们分别是基于字符串的模板基于操作的模板基于虚拟的模板本文是这个系列的第一篇,着重介绍基于字符串的模板引擎的实现原理,分析它的优点缺点以及使用的场景。
这是一个系列文章,将会介绍目前Web前端领域里用到的三种模板引擎技术,它们分别是:
基于字符串的模板
基于Dom操作的模板
基于虚拟Dom的模板
本文是这个系列的第一篇,着重介绍基于字符串的模板引擎的实现原理,分析它的优点缺点以及使用的场景。
进入正文之前,我们先回顾一下在模板引擎出现之前,暂且称之为“石器时代”,我们是如何利用JS改变页面结构的。对于下面的代码:
我们正处于刀耕火种的石器时代
如果我们需要修改container里面的内容,一般有2种方法:
通过JS的DOM API直接操作DOM
var newTxt = "石器时代需要自己撸工具,摩擦摩擦,似魔鬼的步伐..."; var container = document.getElementById("container"); var desc = document.createElement("H1"); var txt = document.createTextNode(newTxt); desc.appendChild(txt); container.replaceChild(desc, container.childNodes[0]);
通过innerHTML批量修改DOM结构
var newTxt = "石器时代需要自己撸工具,摩擦摩擦,似魔鬼的步伐..."; var template = "" + newTxt + "
"; var container = document.getElementById("container"); container.innerHTML=template;
相比之下,第二种方式通过innerHTML更新DOM要简单许多,它无需考虑DOM的层级结构,只要做简单的字符串拼接就能实现需求。但这种方式的问题是代码可读性很差,同时开发者还必须保证最终拼接的字符串的正确性。当需要作出修改时,面对一坨的字符也很痛苦。
在上面的例子中,我们的需求是将一个变量注入到模板当中,类似ES6的模板字符串:
var newTxt = "石器时代需要自己撸工具,摩擦摩擦,似魔鬼的步伐..."; var template = `${newTxt}
`;
但ES6这种现代化的常规武器,对石器时代而言是天方夜谭。部落里的老司机凭借深厚的JS功底,撸出了各种基于字符串的模板。这些模板又可以细分为2类:一种是不包含逻辑处理,只作数据绑定用的,如mustache.js;另一种是既有逻辑处理,也有数据绑定的,如EJS。
下面,我以EJS的语法为例,实现一个简单的字符串模板引擎。模版引擎的编译流程如下:
1.首先,需要编译模板字符串,将其转换为JS能够理解的语法。第一步是利用正则表达式,区分出字符串中哪些是模板语法,哪些是正常的HTML标签。以下是一个EJS语法的例子:
在‘<%=’和‘%>’之间是JS的表达式,而在‘<%’和’%>‘之间是普通的JS语句,可以进行逻辑判断和条件循环等操作。可以使用以下正则表达式抽取:
// 匹配表达式,只能有一行 let evalExpr = /<\%=(.+?)\%>/g; // 匹配语句,可以有多行 let expr = /<\%([sS]+?)\%>/g;
对于普通的HTML标签,需要用自定义的echo函数包裹一下,在使用eval函数编译的时候直接输出字符串。echo函数的定义如下:
// 临时变量,保存编译后的模板字符串 let output = ""; // 直接将html字符串拼接到output后面 function echo(html){ output += html; }
完整的compile函数代码如下:
function compile(template){ // 匹配表达式,只能有一行 let evalExpr = /<\%=(.+?)\%>/g; // 匹配语句,可以有多行 let expr = /<\%([sS]+?)\%>/g; // 内容为空的部分 let empty = /echo("");/g; template = template // 转换JS表达式 .replace(evalExpr, "`); echo( $1 ); echo(`") // 转换JS语句 .replace(expr, "`); $1 echo(`"); // 在模板的最外层包裹一个echo template = "echo(`" + template + "`);"; // 清除空的echo template = template .replace(empty, ""); // 保存编译后的字符串,此处用了ES6的模板字符串特性,相当于eval了一下 let script = `(function parse(data){ // 临时变量,保存编译后的模板字符串 var output = ""; // 直接将html字符串拼接到output后面 function echo(html){ output += html; } // 包含echo的模板字符串 ${ template } return output; })`; return script; }
经过正则表达式处理后,这段代码:
会转化为:
echo(`
完整代码亦可见JSFiddle
2.第二步,我们将模板中用到的数据data注入到compile函数的parse子函数中,生成最终的字符串。
3.最后,我们再通过innerHTML,把字符串插入到DOM合适的位置。
字符串模板之所以能够更新页面,最核心的原理是使用innerHTML这个api将字符串直接插入到DOM节点中。因此,我们分析字符串模板的优缺点就离不开使用innerHTML更新DOM的优缺点。先谈谈优点:
直观,容易理解。更新后的DOM结构可以一目了然的反映在字符串当中。
容易维护。当需要更改模板时,直接改相应字符串就可以,新人也容易上手。
可用于服务端渲染。简单的字符串拼接,不依赖DOM,对应的字符串可由服务器端直接生成。
再来谈谈缺点:
安全隐患。模板字符串中完全可以出现此类代码:
慢!特别对于需要频繁更新的场景。由于innerHTML是直接替换掉原有元素,因此就涉及到相应节点和对应事件的卸载,然后再装载新的节点和事件。在这个过程中,界面也会被重排和重绘,对性能是严重的损耗。
不智能。当只需要修改模板里面的某一部分数据时,整个模板页都需要被刷新。
维护困难。这不是打脸嘛,上面才说了容易维护,这里又讲维护困难!?这当然是有原因的嘛。当不需要考虑性能的时候,一个页面可能只需要维护一个模板,这难道不简单?但考虑到性能的时候,就需要对模板进行拆分和拼装,维护这些相互依赖的模板会让人很崩溃。
综上所述,我们可以很简单的总结出字符串模板引擎的使用场景:如果你的应用比较简单,交互也不多,也希望有一个快速的首屏时间,请使用字符串模板引擎。反之,你硬要上字符串模板引擎的话,我建议你先看看我下一期或者下下一期的文章再做决定,哈哈哈哈~
未完待续...
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/84243.html
摘要:置换型模板引擎的优点实现简单,缺点效率低,无法满足高负载的应用请求。用途百度词条模板引擎可以让网站程序实现界面与数据分离,业务代码与逻辑代码的分离,提升开发效率,良好的设计也提高了代码的复用性。前端模板的出现使得前后端分离成为可能。 模板引擎 模板引擎-百度词条 什么是模板引擎?(百度词条) 模板引擎(这里特指用于Web开发的模板引擎)是为了使用户界面与业务数据分离而产生的,它可以生成...
摘要:简单来说,模板最本质的作用是变静为动,一切利于这方面的都是优势,不利于的都是劣势。二选择的原因全球最受欢迎的模板引擎是全球使用率最高的模板引擎,所以当之无愧是全球最受欢迎的模板引擎。创建更为复杂一些,当时功能更加强大。 showImg(https://segmentfault.com/img/bVbb3kg?w=775&h=216); 为什么需要使用模板引擎? 关于为什么要使用模板引擎...
摘要:欢迎大家收看聊一聊系列,这一套系列文章,可以帮助前端工程师们了解前端的方方面面不仅仅是代码作为现代应用,的大量使用,使得前端工程师们日常的开发少不了拼装模板,渲染模板。我们今天就来聊聊,拼装与渲染模板的那些事儿。一改俱改,一板两用。 欢迎大家收看聊一聊系列,这一套系列文章,可以帮助前端工程师们了解前端的方方面面(不仅仅是代码):https://segmentfault.com/blog...
摘要:欢迎大家收看聊一聊系列,这一套系列文章,可以帮助前端工程师们了解前端的方方面面不仅仅是代码作为现代应用,的大量使用,使得前端工程师们日常的开发少不了拼装模板,渲染模板。我们今天就来聊聊,拼装与渲染模板的那些事儿。一改俱改,一板两用。 欢迎大家收看聊一聊系列,这一套系列文章,可以帮助前端工程师们了解前端的方方面面(不仅仅是代码):https://segmentfault.com/blog...
摘要:欢迎大家收看聊一聊系列,这一套系列文章,可以帮助前端工程师们了解前端的方方面面不仅仅是代码作为现代应用,的大量使用,使得前端工程师们日常的开发少不了拼装模板,渲染模板。我们今天就来聊聊,拼装与渲染模板的那些事儿。一改俱改,一板两用。 欢迎大家收看聊一聊系列,这一套系列文章,可以帮助前端工程师们了解前端的方方面面(不仅仅是代码):https://segmentfault.com/blog...
阅读 1845·2021-11-15 11:39
阅读 1027·2020-12-03 17:06
阅读 682·2019-12-27 11:42
阅读 3247·2019-08-30 13:59
阅读 1436·2019-08-26 13:22
阅读 3267·2019-08-26 12:15
阅读 2453·2019-08-26 10:22
阅读 1540·2019-08-23 18:40