美文网首页
es6实现简单模板编译

es6实现简单模板编译

作者: Stevenzwzhai | 来源:发表于2017-01-15 15:49 被阅读624次

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

    现在有各种框架,其中一个主要模块就是关于template。最火的vue、react等框架,在这一块上也是是下足了功...

  • es6中有新意的特性

    说起es6大家都很熟悉,有些es6新特性chrome等高级浏览器已经实现,不用我们去编译了。今天我简单说下es6的...

  • ES6(8)、新版的类

    1、什么是类 类是拥有相同属性的对象,用于创建对象的模板。 2、如何实现类 1、ES6之前: (1)、实现简单的类...

  • ES6常用新特性

    ES6新特性介绍 模板字符串 模板字符串实现字符串拼接 模板字符串实现多行字符串 结构赋值 对象的解构赋值 数组的...

  • C++ traits使用

    traits一般是利用编译器的能力来获取一些信息。采取的实现方案是模板与模板特化。 实现细节:模板类与static...

  • 模块加载器

    浏览器端javascript依赖 几种实现方案 1.import es6规范,编译施加载,能够在编译时进行静态分析...

  • es6常用知识

    es6编译 let、const const常量 模板字符串 对象的扩展(属性和方法的简洁表达式) demo4 数组...

  • 06Vue 源码解析3

    Vue 源码解析3 模板编译 模板编译的主要目标是将模板(template)转为渲染函数(render) 模板编译...

  • JS模拟实现bind,call,apply

    call apply bind 简单实现 函数柯里化的实现 构造函数的实现 ES6实现 结合实现

  • Vue.js 源码分析——模板编译和组件化

    一、 模板编译 模板编译介绍:模板编译的主要目的是将模板(template)转换为渲染函数(render) 渲染函...

网友评论

      本文标题:es6实现简单模板编译

      本文链接:https://www.haomeiwen.com/subject/mtnybttx.html