简易前端模板引擎

模板解析

解决的问题:

将data和js+html片段解析成html片段,完成赋值和js逻辑,如下所示:

输入:

var data = {     name: 'hwm',     articles: [{ title: 'the first one' }, { title: 'the last one' }] }; tpl = '<p>Hi my name is <%this.name%>.</p><p>My articles are listed as followed:</p>'     + '<ul>'     + '<%for(var i = 0; i < this.articles.length; i++) {%>'     + '<li><%this.articles[i].title%></li>'     + '<%}%>'     + '</ul>';

核心思想:

(1)将js片段、赋值片段、html片段解析出来,主要依赖于正则表达式

// 匹配被标识的片段 var reg = /<%(.*?(?=%>))%>/g; // 匹配if、for等开头的逻辑代码 var logicalReg = /^(( )?(if|for|while|else|{|}|switch|case|break))(.*)?/g;

(2)解析结果均是字符串,通过new Function()的方法,可以将字符串传入函数,当做函数体然后执行

于是在字符串的逻辑就是构建一个数组,然后将html和赋值片段push到数组,将逻辑片段添加到字符串,然后通过call将data传入函数体并执行;

// 匹配被标识的片段 var reg = /<%(.*?(?=%>))%>/g; // 匹配if、for等开头的逻辑代码 var logicalReg = /^(( )?(if|for|while|else|{|}|switch|case|break))(.*)?/g; var match; var result = 'var result = [];\n'; var index = 0; // 使用exec方法,得到匹配内容和匹配结果 while (match = reg.exec(tpl)) {     addCode(tpl.slice(index, match.index));     addCode(match[1], true);     index = match.index + match[0].length; } addCode(tpl.slice(index, tpl.length)); result += 'return result.join("")'; result = result.replace(/[\t\n\r]/g, ''); return new Function(result); function addCode(code, isJs) {     // 保证赋值代码不被引号包裹,js逻辑代码直接拼在字符串中     isJs ? result += (code.match(logicalReg) ? code + '\n' : 'result.push(' + code + ');\n')         : result += 'result.push("' + code.replace(/"/g, '\\"') + '");\n'; }

(3)建立缓存,当数据变化,模板没有变化时,直接从缓存中调用即可,无需重复解析;

(function () {     var cache = {};     this.tmpl = function (id, tpl, data) {         var parser = cache[id] || function () {

                // 解析代码,同上

        }();         cache[id] = parser;         return parser.call(data);     }; })();

备注:主要参考文章链接如下

http://ejohn.org/blog/javascript-micro-templating/

http://krasimirtsonev.com/blog/article/Javascript-template-engine-in-just-20-line

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏青玉伏案

算法与数据结构(二) 栈与队列的线性和链式表示(Swift版)

数据结构中的栈与队列还是经常使用的,栈与队列其实就是线性表的一种应用。因为线性队列分为顺序存储和链式存储,所以栈可以分为链栈和顺序栈,队列也可分为顺序队列和链队...

191100
来自专栏农夫安全

【weakfilescan】敏感文件扫描工具

weakfilescan 基于爬虫,动态收集扫描目标相关信息后进行二次整理形成字典规则,利用动态规则的多线程敏感信息泄露检测工具,支持多种个性化定制选项,包括...

48180
来自专栏Java学习网

Java中的内存泄漏学习

Java中的内存泄漏学习   Java语言的一个关键的优势就是它的内存管理机制。你只管创建对象,Java的垃圾回收器帮你分配以及回收内存。然而,实际的情况并没...

23880
来自专栏xingoo, 一个梦想做发明家的程序员

数字按照不同格式转换成字符串

  如果自己写函数,不使用itoa怎么判断呢?   我们用通常的办法,对数字进行每位的除商,得到后与字符'0'相加。 flag = 0; ...

213100
来自专栏java一日一条

JVM 进行线程同步背后的原理

所有的 Java 程序都会被翻译为包含字节码的 class 文件,字节码是 JVM 的机器语言。这篇文章将阐述 JVM 是如何处理线程同步以及相关的字节码。

10610
来自专栏null的专栏

Python技巧——list与字符串互相转换

在Python的编程中,经常会涉及到字符串与list之间的转换问题,下面就将两者之间的转换做一个梳理。 1、list转换成字符串 命令:list() 例子: ?...

27430
来自专栏Jackson0714

【.Net底层剖析】3.用IL来理解属性

34370
来自专栏前端菜鸟变老鸟

ES6(二):Promise

ES6之前解决异步编程只能使用回调函数或事件,ES6中加入了 Promise,使得异步编程更加简洁直观和合理

13030
来自专栏C/C++基础

new和delete的使用规范

C++的动态内存管理是通过new和delete两个操作来完成的,即用new来申请空间,用delete来释放空间。在使用new和delete时,注意以下原则。

12620
来自专栏个人随笔

论 Java 的访问权限

Java中成员访问权限 Java中的访问权限控制符有四个: 作用域_____当前类____同一package___子孙类____其他package publi...

40580

扫码关注云+社区

领取腾讯云代金券