手写一个js模版引擎

目标将如下js语句:

'<ul class="{{ =$data.myclass }}">'+
'{{for(let i = 0;i < 3;i++){}}'+
'<li>{{ =i }}</li>'+
'{{}}}'+
'</ul>';

转换为字符串:

<ul class="active">
    <li>0</li>
    <li>1</li>
    <li>2</li>
</ul>

书写语法为:

{{ =变量值 }}               说明:值是获取值必须在左右两个双大括号中添加=
{{ 写js表达式 }}            说明:表达式两边必须添加双大括号

实现步骤一【去掉所有的换行】:

const temp2 = temp.replace(/[\r\n]/g, '');
结果为:<ul class="{{ =$data.myclass }}">{{for(let i = 0;i < 3;i++){}}<li>{{ =i }}</li>{{}}}</ul>

实现步骤二【将双大括号左右两侧的单引号或双引号添加斜线】:

const temp3 = temp2.replace(/^(.+?)\{\{|\}\}(.+?)\{\{|\}\}(.+?)$/g, function (a) {
        return a.replace(/(['"])/g, '\\\$1');
    })
第一个正则表达式为匹配双大括号左右两侧的内容
第二个正则表达式为将单引号或双引号添加斜线进行转义
结果为:<ul class=\"{{ =$data.myclass }}\">{{for(let i = 0;i < 3;i++){}}<li>{{ =i }}</li>{{}}}</ul>

实现步骤三【替换{{ = }}中的内容】:

var temp4 = temp3.replace(/\{\{\s*=\s*(.+?)\}\}/g, "';$out+=$1;$out+='");
结果为:<ul class=\"';$out+=$data.myclass ;$out+='\">{{for(let i = 0;i < 3;i++){}}<li>';$out+=i ;$out+='</li>{{}}}</ul>
这句话的作用是将一个完整的语句根据括号的位置拆分成两句,举个例子:
'我是{{ =变量 }}人'拆分为:'我是';$out +=变量;$out +=‘人'
假设变量的值为:中国。并且我们在拆分后的语句前添加var $out=则组合成的完整语句为:var $out='我是';$out +=变量;$out +=‘人'

实现步骤四【替换{{ }}中的内容】:

 var temp5  = temp4.replace(/\{\{(.+?)\}\}/g, "';$1$out+='");
结果为:ul class=\"';$out+=$data.myclass ;$out+='\">';for(let i = 0;i < 3;i++){$out+='<li>';$out+=i ;$out+='</li>';}$out+='</ul>
这句话的作用是双大括号中的js表达式提取出来不要让其在字符串的引号中,这样在最后直接执行。

实现步骤五【在字符串前后分别添加拼接字符串】:

var temp6 =  "var $out='" + temp5 + "';return new String($out);";
结果为:var $out='<ul class=\"';$out+=$data.myclass ;$out+='\">';for(let i = 0;i < 3;i++){$out+='<li>';$out+=i ;$out+='</li>';}$out+='</ul>';return new String($out);
作用是构建一个可执行的js语句

实现步骤五【构建可执行函数传递参数返回结果】:

参数param为:const param = {myclass:'active'}
//这一步的作用是将字符串转换为函数,其中第一个参数为函数的参数名
 var Render = new Function('$data', temp6);
//执行函数返回结果
 var result = new Render(param).toString();

抽取公共方法:

//第一个参数为模版语句,第二个参数为模版语句中的变量
function template(source, data) {
            var code = "var $out='" + source.replace(/[\r\n]/g, '').replace(/^(.+?)\{\{|\}\}(.+?)\{\{|\}\}(.+?)$/g, function (a) {
                return a.replace(/(['"])/g, '\\\$1');
            }).replace(/\{\{\s*=\s*(.+?)\}\}/g, "';$out+=$1;$out+='").replace(/\{\{(.+?)\}\}/g, "';$1$out+='") + "';return new String($out);";
            var Render = new Function('$data', code);
            return new Render(data).toString();
        }

总结:利用正则表达式将特定的语句进行替换,从而实现模版引擎。
参考:https://gitee.com/qinshenxue/datepicker项目中的源码部分。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 官网 中文版本 好的网站 Content-type: text/htmlBASH Section: User ...
    不排版阅读 4,485评论 0 5
  • 概要 64学时 3.5学分 章节安排 电子商务网站概况 HTML5+CSS3 JavaScript Node 电子...
    阿啊阿吖丁阅读 9,350评论 0 3
  • 一、Python简介和环境搭建以及pip的安装 4课时实验课主要内容 【Python简介】: Python 是一个...
    _小老虎_阅读 5,846评论 0 10
  • 本文介绍 Ruby 基本的数据类型,主要参考《Ruby编程语言》。Ruby支持的数据类型包括基本的Number、S...
    零小白阅读 12,215评论 0 11
  • 字符串和字符 [TOC] 字符串是例如 "hello, world" , "albatross" 这样的有序的 C...
    伍哥___阅读 1,119评论 0 0