栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > Web开发 > JavaScript

咱一起来手撸一个模板引擎吧。

JavaScript 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

咱一起来手撸一个模板引擎吧。

    jQuery时代的时候,相信有很多人用过template,(也就是模板引擎),那这样的一个模板引擎,大概长什么样?它的实现机理又是怎样的呢?咱自己手动写一个模板引擎实现,一起看看这个方便实用的东西内部是如何工作的吧。

    传统字符串拼接的代码:

    用模板引擎的代码:

    模板引擎直观,易懂,易拷贝,易修改,动态的特点,让它在当前主流的页面渲染模式中占着最主要的比重,从jQuery时代的传统模板(上面,写在单独的script标签),到MVVM框架的常见模板(直接在标签里写各种模板),以及ES6/7后出现的`${}`模板字符串,都是各种不同类型的模板引擎。因为现在与最初的前端写页面,后台绑数据不同(难改,改动量大,难理解),后台是写接口,前端是调接口,前后端联调,业务改变了,前端稍作修改即可(后台基本可以不动,除非需求改动大),而这种模式下,前端首先是不知道会返回多少数据量,只知道字段名,所以前端首先都是根据字段名写好各个模块的模板,再链接上后台的数据,而模板引擎是相当方便也相当好用的一种方式。代码改动起来也简单。比传统的字符串拼接要简单有用得多。

    传统的模板引擎呢,也难免存在一些小缺陷,因为有数据才有内容,所以的话大多需要同步工作,什么意思呢?就是数据要先拿到,再加载模板。现在新的MVVM模板比如vue都是双向的,模板即数据,view即data,相对来说性能更好,体验也更佳。

    而本次我们要实现的呢,大概是这样的:

    最终呢,页面上输出:

    要实现这个,我们需要先明白模板引擎的工作原理,它的原理很简单,利用符合某种正则匹配规则(自己定义,我这里用的是{%%}和{%=%}这个,带“=”的代表是值,不带的则是一个js函数表达式。)的字符串,将之替换成js代码,并在写入的时候执行。

    那怎么做呢?我们一步步来看:

    首先是要匹配对应的字符串吧?用正则去匹配带{%%}和{%=%}标识符的字符串。

    咱们match一下,可以看到我们所有带有所需标识符的各个片段都被我们搜索出来了。

    接下来呢?

    看下这段代码:

var data = [{name: "dorsey",age: 25,sex: "男"},{name: "sen",age: 25,sex: "女"}];
var tmpl = new Function ("data","for (var i = 0; i < data.length; i ++) { console.log("名字: " + data[i].name + " 年龄: " + data[i].age + " 性别: " + data[i].sex); }");
tmpl(data);

再看看输出:

    是不是很神奇?因为我写的是一段字符串啊。console.log()那些代码都是字符串啊,居然还能执行?这是因为js本身构造函数时就具备了这个能力,这样跟我们想要的结果好像很接近很接近了,对吧?

    实际上我们要做的,就是取出逻辑部分(js代码执行部分),跟字符串部分,装进new Function,这样就基本实现了我们想要的结果。js是一门动态语言,用在这上是最方便也最容易的。(静态语言类似于C#据说要先将模板转成动态类,再用反射动态执行类中的代码,比较复杂)

    现在我们完成了哪些呢?

    第一:拿到要修改成js逻辑的字符串片段

    第二:知道怎么把字符串转成js逻辑代码

    那还差什么呢?注意到new function内部的字符串是一整段的,而我们现在有的还只是一小段一小段的片段,最重要的一步来了,拼接,拼接成一个特殊的字符串,看看这个字符串长什么样哈,你会发现,哦。。。原来是这样。。。

    那每一段都有了,要拼凑成一个这样的代码不是很简单了吗?确实不难,注意下细节就OK了。

    这里的话replace是替换,当正则匹配有多条规则时,其回调返回的参数这里做下小说明:

    match:是匹配出来的字符片段

    rank1:正则匹配当有多条规则时,有个优先级,从左到右一个个匹配(“|”根据或符号),是第一个级别的带匹配符号{%=%}的整段字符串。

    content1:则是rank1对应的不带匹配符号的内部内容。后续rank2,content2也是一样

    offset是偏移量,对应的是这个片段在当前整个字符串的位置。

    另外的话呢,由于我们是把字符串转成js代码,会存在着XSS漏洞攻击的可能,所以把代码转成安全的符号,大概这样:

    (这部分还没嵌进去)

    最后呢,贴一下代码吧:(代码贴上去不会换行,勉强贴成这样子了)

    html部分

   

   

   

    模板引擎模块测试页

   

        html,body,div,ul,li,p{margin:0;padding:0;}

        ul{list-style:none}

   

    

   

   

   

    

   

js部分

const _Tmpl = {


tmpl (tmplID,d) {


let html = document.getElementById(tmplID).innerHTML,

reg = /({%=([sS]+?)%})|({%([sS]+?)%})/g;


let tran = {

"n": "\n",

"r": "\r",

"t": "\t"

}

let str_fn = "let tmpl = "";tmpl += "";

let index = 0;

html.replace(reg, (match, rank1, content1, rank2, content2, offset) => {

str_fn += html.slice(index,offset).replace(/\|'|r|n|t/g, function(match) { return tran[match];});//换行符,table,空格转义

if(rank1){

str_fn += "" + " + content1 + " + "";

}

if(rank2){

str_fn += "";" + content2 + "tmpl += "";

}

index = offset + match.length;

});

str_fn += "";return tmpl;"

let template = new Function("d",str_fn);

return template(d);

},

xssRsp (html) {

return String(html)

.replace(/&/g,"&")

.replace(/

.replace(/>/g,">")

.replace(/"/g,""")

.replace(/'/g,"'");

},

test () {

}

}

export default _Tmpl;

    现在暂时没push上去。

    这样一个简单的模板引擎就出来了= =。是不是很cool?





转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/245577.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号