专栏首页Young Dreamer简易前端模板引擎

简易前端模板引擎

模板解析

解决的问题:

将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 条评论
登录 后参与评论

相关文章

  • web worker 扫盲篇

    什么是woker 官方的解释是这样的: worker是一个对象,通过构造函数Worker创建,参数就是一个js文件的路径;文件中的js代码将运行在主线程之外的w...

    用户1217459
  • VUE中的v-if与v-show

    1.共同点 都是动态显示DOM元素 2.区别 (1)手段:v-if是动态的向DOM树内添加或者删除DOM元素;v-show是通过设置DOM元素的display样...

    用户1217459
  • httpd配置ResponseHeader

      今天遇到一个问题:我把项目编译后的静态文件发布到开发机上,开发机使用httpd启的静态文件服务,页面的访问是在特制的壳浏览器里面,我更新了代码后,发现页面被...

    用户1217459
  • DIY一个Sketch插件,生成猫猫狗狗的全家福

    最近朋友圈都在玩的全家福: ? 看了下是使用 cocos2D 引擎制作的, http://www.cocos.com/creator 主要是图片合成,利用前端...

    mixlab
  • struts的声明式异常处理 demo

    情景 使用Struts封装的下载文件的功能 当下载文件找不到的时候,struts获取的InputStream为null 这个时候,就会报500错误 ja...

    用户1174983
  • C#3.0新增功能03 隐式类型本地变量

    从 Visual C# 3.0 开始,在方法范围内声明的变量可以具有隐式“类型”var。 隐式类型本地变量为强类型,就像用户已经自行声明该类型,但编译器决定类型...

    张传宁老师
  • js的深拷贝,浅拷贝

    对于字符串类型,浅复制是对值的复制,对于对象来说,浅复制是对对象地址的复制,并没 有开辟新的栈,也就是复制的结果是两个对象指向同一个地址,修改其中一个对象的属性...

    山河木马
  • 如何防止网站被扒的解决方法!

    这个代码能够直接保护整个站,而不再是单个页面,直接把代码放到自己的网站上,如果是博客建议放到header.php头部文件,如果是单页面直接放到首页即可!

    空木白博客
  • 20.Swift学习之扩展

    扩展可以使已有的类型遵循一个或多个协议。在这种情况下,协议名的书写方式与类或结构体完全一样:

    YungFan
  • What's New in LLVM 9

    导语 :这绝不仅仅是一篇 WWDC 2017 Session 411 学习笔记。除了有关 LLVM 9.0 的新特性之外,还有关于静态分析器和 Clang 5 ...

    MelonTeam

扫码关注云+社区

领取腾讯云代金券