这是一个系列文章,将会介绍目前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 = /\/g;

对于普通的HTML标签,需要用自定义的echo函数包裹一下,在使用eval函数编译的时候直接输出字符串。echo函数的定义如下:

// 临时变量,保存编译后的模板字符串

let output = "";

// 直接将html字符串拼接到output后面

function echo(html){

output += html;

}

完整的compile函数代码如下:

function compile(template){

// 匹配表达式,只能有一行

let evalExpr = /\/g;

// 匹配语句,可以有多行

let expr = /\/g;

// 内容为空的部分

let empty = /echo\(\"\"\);/g;

template = template

// 转换JS表达式

.replace(evalExpr, '`); \n echo( $1 ); \n echo(`')

// 转换JS语句

.replace(expr, '`); \n $1 \n 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(`

  • `);

for(var i=0; i

echo(`

`);

echo( data.supplies[i] );

echo(``);

}

echo(`

`);

2.第二步,我们将模板中用到的数据data注入到compile函数的parse子函数中,生成最终的字符串。

3.最后,我们再通过innerHTML,把字符串插入到DOM合适的位置。

字符串模板之所以能够更新页面,最核心的原理是使用innerHTML这个api将字符串直接插入到DOM节点中。因此,我们分析字符串模板的优缺点就离不开使用innerHTML更新DOM的优缺点。先谈谈优点:

直观,容易理解。更新后的DOM结构可以一目了然的反映在字符串当中。

容易维护。当需要更改模板时,直接改相应字符串就可以,新人也容易上手。

可用于服务端渲染。简单的字符串拼接,不依赖DOM,对应的字符串可由服务器端直接生成。

再来谈谈缺点:

安全隐患。模板字符串中完全可以出现此类代码:

慢!特别对于需要频繁更新的场景。由于innerHTML是直接替换掉原有元素,因此就涉及到相应节点和对应事件的卸载,然后再装载新的节点和事件。在这个过程中,界面也会被重排和重绘,对性能是严重的损耗。

不智能。当只需要修改模板里面的某一部分数据时,整个模板页都需要被刷新。

维护困难。这不是打脸嘛,上面才说了容易维护,这里又讲维护困难!?这当然是有原因的嘛。当不需要考虑性能的时候,一个页面可能只需要维护一个模板,这难道不简单?但考虑到性能的时候,就需要对模板进行拆分和拼装,维护这些相互依赖的模板会让人很崩溃。

综上所述,我们可以很简单的总结出字符串模板引擎的使用场景:如果你的应用比较简单,交互也不多,也希望有一个快速的首屏时间,请使用字符串模板引擎。反之,你硬要上字符串模板引擎的话,我建议你先看看我下一期或者下下一期的文章再做决定,哈哈哈哈~

未完待续...

html模板引擎 字符串长度,Web前端模板引擎の字符串模板相关推荐

  1. 好程序员web前端教程:字符串

    为什么80%的码农都做不了架构师?>>>    好程序员web前端教程:字符串,观察某宝网商品数据,有一个东西叫服务器>>>>js的作用重要作用之一>& ...

  2. bootstrap网页模板源码_Go Web 编程--超详细的模板库应用指南

    如果你有过Web编程的经验,那么或多或少都听说过或者使用过模板.简而言之,模板是可用于创建动态内容的文本文件.例如,你有一个网站导航栏的模板,其中动态内容的一部分可能是根据当前用户是否登录显示登录还是 ...

  3. HTML在前端开发中起到的作用,什么是字符串,web前端开发里起到什么作用

    观察某宝商品数据,有一个东西叫服务器>>>>js的作用重要作用之一>>>>交互>>>>人机交互(事件)>>>& ...

  4. js判断中文字符串长度和js截取中文字符串

    //获取字符串长度String.prototype.strLen = function() { var len = 0; for (var i = 0; i < this.length; i++ ...

  5. c ++中字符串长度的_C ++中的字符串长度

    c ++中字符串长度的 The string length in C++ can be calculated or found by various methods. Here, in this tu ...

  6. php与js字符串长度怎么算,JS判断字符串长度的5个方法

    主要介绍JS判断字符串长度的5个方法,并且区分中文和英文,需要的朋友可以参考下 目的:计算字符串长度(英文占1个字符,中文汉字占2个字符) 方法一: 代码如下: String.prototype.gb ...

  7. js根据判断改变html字符串长度,js如何判断输入字符串长度

    js判断输入字符串长度(汉字算两个字符,字母数字算一个) 文本输入时,由于数据库表字段长度限制会导致提交失败,因此想到了此方法验证. 废话不多说上代码: js判断输入字符串长度(汉字算两个字符,字母数 ...

  8. 程序员如何解决中年危机?web前端开发工程师简历模板

    异步复制 MySQL的复制默认是异步的,主从复制至少需要两个MYSQL服务,这些MySQL服务可以分布在不同的服务器上,也可以在同一台服务器上. MySQL主从异步复制是最常见的复制场景.数据的完整性 ...

  9. 判断html()中有长度,VBS 字符串长度判断的问题

    对于给你一个字符串你应该怎样判断他的字符串长度,试举一些典型的例子C语言--字符串长度的计算方法提示:(1)计算字符串长度时关键是要注意辨认转义字符:(2)一个转义字符总是以反斜杠开始,再加一个其他字 ...

最新文章

  1. php 执行系统命令函数
  2. 前端 ---JS中的面向对象
  3. WinForm读取指定的config文件的内容
  4. UVA10561 Treblecross
  5. css初始化_利用CSS变量实现炫酷的悬浮效果
  6. 计算机网络和通信,计算机网络与通信技术
  7. 电脑运行java游戏,电脑运行软件卡顿?这几招游戏或是办公,让你速度飞起!...
  8. linux删除目录tmpab是什么意思_linux 下tmp目录文件怎么被删除的?
  9. 解决js动态改变dom元素属性后页面及时渲染问题
  10. php 5.4中php-fpm 的重启、终止操作命令
  11. 【Proteus】超声波测距
  12. vue运用JsBarcode生成一维码
  13. 简书项目实战-main首页开发
  14. 软件配置管理概念-3,CM系统的概念
  15. [应用广播], 一览华夏文化,诗词三万首震撼上线
  16. php支持连接sql server数据库
  17. 碗状碎块三维模型的下载(.PLY格式)3D model file with Bowl-shaped Broken Piece (.ply format)
  18. 软件设计的不同模型:瀑布式、快速原型法以及迭代式
  19. SAP报工时修改工作中心
  20. MFC中TeeChart插件绘图

热门文章

  1. 分分钟教会你使用HTML写Web页面
  2. HostMonitor使用介绍
  3. 面试结尾——你有什么问题?
  4. random模块——生成伪随机数
  5. 彻底弄懂flex布局
  6. Erlang Start![3]
  7. 【Git】git使用 - 各种常用场景命令解决
  8. JavaScript_原型和继承(2017-03-15)
  9. Atitit java 二维码识别 图片识别
  10. AJAX实现简单的注册页面异步请求