现在有各种框架,其中一个主要模块就是关于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实现简单模板编译的更多相关文章

  1. ES6中的模板字符串和新XSS Payload

    ES6中的模板字符串和新XSS Payload 众所周知,在XSS的实战对抗中,由于防守方经常会采用各种各样严格的过滤手段来过滤输入,所以我们使用的XSS Payload也会根据实际情况作出各种各样的 ...

  2. es6学习笔记--模板字符串

    这几天简单看了一下深入浅出es6这本书,感觉特实用,学习了一个新特性---模板字符串在项目开发中,拼接字符串是不可缺少的,动态创建dom元素以及js操作数据都要拼接字符串,在es6出来之前,我们都通常 ...

  3. [Vue源码]一起来学Vue模板编译原理(一)-Template生成AST

    本文我们一起通过学习Vue模板编译原理(一)-Template生成AST来分析Vue源码.预计接下来会围绕Vue源码来整理一些文章,如下. 一起来学Vue双向绑定原理-数据劫持和发布订阅 一起来学Vu ...

  4. [Vue源码]一起来学Vue模板编译原理(二)-AST生成Render字符串

    本文我们一起通过学习Vue模板编译原理(二)-AST生成Render字符串来分析Vue源码.预计接下来会围绕Vue源码来整理一些文章,如下. 一起来学Vue双向绑定原理-数据劫持和发布订阅 一起来学V ...

  5. PyInstaller 安装方法 及简单的编译exe (python3)

    安装PyInstaller //地址 https://github.com/pyinstaller/pyinstaller/tree/python3 //上面的链接已经失效,新的(20160809更) ...

  6. C#基础--.net平台的重要组成部分以及.net程序简单的编译原理

    .net平台的组成只要有两部分   FCL:框架类库    CLR:公共语言运行时 .net程序简单的编译原理 1.0:使用C#编译器(csc.exe) 将C#源代码编译成程序集+{编译之前:会检查C ...

  7. C++ Primer 学习笔记_79_模板与泛型编程 --模板编译模型

    模板与泛型编程 --模板编译模型 引言: 当编译器看到模板定义的时候,它不马上产生代码.仅仅有在用到模板时,假设调用了函数模板或定义了模板的对象的时候,编译器才产生特定类型的模板实例. 一般而言,当调 ...

  8. 再起航,我的学习笔记之JavaScript设计模式30(简单模板模式)

    简单模板模式 概念介绍 简单模板模式(Simple template): 通过格式化字符串拼凑出视图避免创建视图时大量节点操作,优化内存开销. 创建模板 在实际的业务中如果我们需要进行前后台交互,或多 ...

  9. helm-chart-2-chart结构和简单模板

    1, chart 结构介绍 我们创建一个chart 并查看其结构 右侧注释为其文件的的解释 $ helm create mychart $ cd mychart/ $ tree ├── charts ...

随机推荐

  1. P1424 小鱼的航程(改进版)

    题目背景 原来的题目太简单,现改进让小鱼周末也休息,请已经做过重做该题. 题目描述 有一只小鱼,它上午游泳150公里,下午游泳100公里,晚上和周末都休息(实行双休日),假设从周x(1<=x&l ...

  2. Linux---who命令学习

    who命令 获取正在登录系统的用户 使用Linux的who命令 第一个参数book代表用户名,第二个参数tty7代表终端名,第三个参数代表时间,第四个参数代表用户的登录地址. 阅读手册 使用命令读手册 ...

  3. 如何提高mysql的安全性?

    1.如果 MySQL 客户端和服务器端的连接需要跨越并通过不可信任的网络,那么需要使用 ssh 隧道来加密该连接的通信.2.使用 set password 语句来修改用户的密码,先“mysql -u ...

  4. caffe新版本的各种软件

    系统重装了,于是,我想装就体验一下最新的各种东西吧. anaconda最新的 cuda最新的 cudnn最新的 本来安装好了没问题.caffe编译也通过了.但是不能用,缺少python opencv和 ...

  5. 修改与遍历MAP

    package com.*; import java.util.*; /** * Created by HP on 2018/8/2. */ public class Test { //定义一个用于转 ...

  6. 理解 JavaScript 作用域(转)

    简介 JavaScript 有个特性称为作用域.尽管对于很多开发新手来说,作用域的概念不容易理解,我会尽可能地从最简单的角度向你解释它们.理解作用域能让你编写更优雅.错误更少的代码,并能帮助你实现强大 ...

  7. iOS之旅--隐藏(去除)导航栏底部横线

    iOS之旅--隐藏(去除)导航栏底部横线 iOS开发大部分情况下会使用到导航栏,由于我司的app导航栏需要与下面紧挨着的窗口颜色一致,导航栏底部的横线就会影响这个美观,LZ使用了以下方法.觉得不错,分 ...

  8. centos6 下查看SELinux状态 关闭SELinux

    转载自:https://blog.csdn.net/boomjane_testingblog/article/details/52859977 SELinux(Security-Enhanced Li ...

  9. Linux文件服务器实战(匿名用户)

    一.进程与线程 二.vsftp服务器 1.文件传输协议(file transfer protocol,FTP) 基于该协议ftp客户端和服务端实现文件共享,上传下载文件 FTP基于TCP协议生成一个虚 ...

  10. 学习python第十三天,函数5 装饰器decorator

    定义:装饰器本质是函数,(装饰其他函数)就是为其他函数添加附加功能原则:1.不能修改被装饰的函数的源代码 2.不能修改装饰的函数的调用方式 实现装饰器知识储备1函数即变量2.高阶函数,满足2个条件之一 ...