es6实现简单模板编译
现在有各种框架,其中一个主要模块就是关于template。最火的vue、react等框架,在这一块上也是是下足了功夫。我也想写一个自己的模板编译工具,所以就做了个简单的实现,主要是使用es6的反引号编译。
1.选择
这里使用es6的反引号去编译文本节点,只要把数据放在scope中,我们就可以使用反引号加“${}”的方式去把变量替换掉模板中的内容。
2.编译内容
首先,我尝试去直接编译一个文本,让变量能够被填充,模板这么写
<div id="app">
<p>your name is ${name}</p>
<p>your age is ${age}</p>
</div>
模板中${}中的内容是要被替换的。首先我们获取文本字符串
const root = document.querySelector('#app');
let htmlFragment = root.innerHTML;
然后我们要找出需要替换的变量名,这里用正则查找
const templateReg = /\${([^{}])+}/g;
let res = null;
let keyArray = [];
//把找到的变量存起来
while(res = reg.exec(htmlFragment)){
let key = res[0].slice(2,res[0].length-1);
keyArray.push(key);
}
我们在js中定义的数据格式是这样的
let data = {
name:"javascript",
age:"22"
}
接下来,我们把js中的数据格式替换掉模板中的
for(let item of keyArray){
let nReg = new RegExp("\\${"+item+"}","g");
htmlFragment = htmlFragment.replace(nReg, '${data["'+item+'"]}');
}
这里说一下为什么要替换,首先是es6中编译字符串中的变量,这个变量必须在scope中,然后,我们的数据不可能是就像一个一个的变量,那样要定义太多,还有就是模板中尽量写法简洁。所以这里把简洁的变量替换为正真的scope中的变量。因为是要动态替换,所以正则表达式每次都要重新定义(注意转义)。
最后就是如何编译的问题,因为我们拿到的是个字符串,而es6是要用反引号来编译,所以这里就需要拼接反引号和字符串进行编译,大家最容易想到的就是eval,但是介于它可能会带来一些不可预知的东西,所以我们使用new Function()的方式。
let str = new Function("return `"+htmlFragment+"`");
root.innerHTML = "";
//这个方法很久之前就有了,并不是最新出的
root.insertAdjacentHTML('afterbegin',str);
3.编译模板
这里借鉴vue的节点编译方式,主要就是对元素节点和文本节点的处理。由于并没有做循环渲染,所以目前只做了对文本节点的处理。基本的思想还是以一颗树的形式去一层一层的编译。
class Compile{ constructor(node){ this.compileNode(node); node.hasChildNodes() ? this.compileNodeList(node.childNodes) : null; } compileNodeList(nodeList){ let childListFn, node; for(node of nodeList){ this.compileNode(node); node.hasChildNodes ? this.compileNodeList(node.childNodes) : null; } } compileNode(node){ console.log(node); if(node.nodeType == 1){ this.compileElement(node); }else if(node.nodeType == 3){ this.compileText(node); } } compileElement(node){ //解析指令 } compileText(node){ //解析模板 node.data; node.data = this.compileTemplate(node.data)(); } compileTemplate(textFragment){ let res = null; let keyArray = []; while(res = templateReg.exec(textFragment)){ let key = res[0].slice(2,res[0].length-1); keyArray.push(key); } for(let item of keyArray){ let nReg = new RegExp("\\${"+item+"}","g"); console.log(nReg.test(textFragment)); textFragment = textFragment.replace(nReg, '${data["'+item+'"]}'); } return new Function("return `"+textFragment+"`"); }}//new这个对象即可new Compile(root);
全部的可以去github上看,这个后续也会加强功能。https://github.com/Stevenzwzhai/plugs/tree/master/es6-template
es6实现简单模板编译的更多相关文章
- ES6中的模板字符串和新XSS Payload
ES6中的模板字符串和新XSS Payload 众所周知,在XSS的实战对抗中,由于防守方经常会采用各种各样严格的过滤手段来过滤输入,所以我们使用的XSS Payload也会根据实际情况作出各种各样的 ...
- es6学习笔记--模板字符串
这几天简单看了一下深入浅出es6这本书,感觉特实用,学习了一个新特性---模板字符串在项目开发中,拼接字符串是不可缺少的,动态创建dom元素以及js操作数据都要拼接字符串,在es6出来之前,我们都通常 ...
- [Vue源码]一起来学Vue模板编译原理(一)-Template生成AST
本文我们一起通过学习Vue模板编译原理(一)-Template生成AST来分析Vue源码.预计接下来会围绕Vue源码来整理一些文章,如下. 一起来学Vue双向绑定原理-数据劫持和发布订阅 一起来学Vu ...
- [Vue源码]一起来学Vue模板编译原理(二)-AST生成Render字符串
本文我们一起通过学习Vue模板编译原理(二)-AST生成Render字符串来分析Vue源码.预计接下来会围绕Vue源码来整理一些文章,如下. 一起来学Vue双向绑定原理-数据劫持和发布订阅 一起来学V ...
- PyInstaller 安装方法 及简单的编译exe (python3)
安装PyInstaller //地址 https://github.com/pyinstaller/pyinstaller/tree/python3 //上面的链接已经失效,新的(20160809更) ...
- C#基础--.net平台的重要组成部分以及.net程序简单的编译原理
.net平台的组成只要有两部分 FCL:框架类库 CLR:公共语言运行时 .net程序简单的编译原理 1.0:使用C#编译器(csc.exe) 将C#源代码编译成程序集+{编译之前:会检查C ...
- C++ Primer 学习笔记_79_模板与泛型编程 --模板编译模型
模板与泛型编程 --模板编译模型 引言: 当编译器看到模板定义的时候,它不马上产生代码.仅仅有在用到模板时,假设调用了函数模板或定义了模板的对象的时候,编译器才产生特定类型的模板实例. 一般而言,当调 ...
- 再起航,我的学习笔记之JavaScript设计模式30(简单模板模式)
简单模板模式 概念介绍 简单模板模式(Simple template): 通过格式化字符串拼凑出视图避免创建视图时大量节点操作,优化内存开销. 创建模板 在实际的业务中如果我们需要进行前后台交互,或多 ...
- helm-chart-2-chart结构和简单模板
1, chart 结构介绍 我们创建一个chart 并查看其结构 右侧注释为其文件的的解释 $ helm create mychart $ cd mychart/ $ tree ├── charts ...
随机推荐
- HDU 4871 Shortest-path tree
先用dijkstra把最短路树建出来,然后就是树的质心分治了. 经过k个点的路径,要么全在子树上,要么经过根结点,因此可以分治. 如果分治的时候选点不好会变成O(n^2),比较极端的情况是比如树是一条 ...
- Python实现接口测试中的常见四种Post请求数据
前情: 在日常的接口测试工作中,模拟接口请求通常有两种方法, 利用工具来模拟,比如fiddler,postman,poster,soapUI等 利用代码来模拟,使用到一些网络模块,比如HttpClie ...
- 2017.9.21 HTML学习总结---多媒体播放系统设计
1.题目:整个页面被划分三个子窗口,上面窗口为页面功能提示区, 下左部分为不同类型播放的功能选项,下右部分为播放系统显示播放信息窗口. (1)网页设计框架: <html> <head ...
- C++ Boost库简介
boost是一个准标准库,相当于STL的延续和扩充,它的设计理念和STL比较接近,都是利用泛型让复用达到最大化.不过对比STL,boost更加实用.STL集中在算法部分,而boost包含了不少工具类, ...
- HTTP 之缓存
这是一篇知识性的文档,主要目的是为了让Web缓存相关概念更容易被开发者理解并应用于实际的应用环境中.为了简要起见,某些实现方面的细节被简化或省略了.如果你更关心细节实现则完全不必耐心看完本文,后面参考 ...
- v-cloak
v-cloak 不需要表达式 用法: 这个指令保持在元素上直到关联实例结束编译.和 CSS 规则如 [v-cloak] { display: none } 一起用时,这个指令可以隐藏未编译的 Must ...
- java.lang.UnsupportedOperationException 原因以及解决方案
如下代码: Map[] cardProds = JsonUtils.getObject(oldCartValue, new TypeReference<Map[]>(){}); List& ...
- Shell学习——Shell分类:登录shell和非登陆shell 交互shell和非交互shell
1.从两个不同维度来划分,是否交互式,是否登录 2.交互式shell和非交互式shell 交互式模式:在终端上执行,shell等待你的输入,并且立即执行你提交的命令.这种模式被称作交互式是因为shel ...
- Ansible学习 ad-hoc命令
Ansible提供两种方式去执行命令,一种是ad-hoc命令,一种是写入Ansible playbook.类似于前者在命令行敲shell,后者是写shell-script脚本,前者解决一些简单的任务, ...
- (转)零基础学习 Hadoop 该如何下手?
推荐一些Hadoop家族系列文章,主要介绍Hadoop家族产品,常用的项目包括Hadoop, Hive, Pig, HBase, Sqoop, Mahout, Zookeeper, Avro, Amb ...