es6實現(xiàn)簡單模板編譯

現(xiàn)在有各種框架,其中一個主要模塊就是關(guān)于template。最火的vue、react等框架,在這一塊上也是是下足了功夫。我也想寫一個自己的模板編譯工具,所以就做了個簡單的實現(xiàn),主要是使用es6的反引號編譯。

1.選擇

這里使用es6的反引號去編譯文本節(jié)點,只要把數(shù)據(jù)放在scope中,我們就可以使用反引號加“${}”的方式去把變量替換掉模板中的內(nèi)容。

2.編譯內(nèi)容

首先,我嘗試去直接編譯一個文本,讓變量能夠被填充,模板這么寫

<div id="app">
     <p>your name is ${name}</p>
     <p>your age is ${age}</p>
</div>

模板中${}中的內(nèi)容是要被替換的。首先我們獲取文本字符串

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中定義的數(shù)據(jù)格式是這樣的

let data = {
     name:"javascript",
     age:"22"
}

接下來,我們把js中的數(shù)據(jù)格式替換掉模板中的

 for(let item of keyArray){
     let nReg = new RegExp("\\${"+item+"}","g");           
     htmlFragment = htmlFragment.replace(nReg, '${data["'+item+'"]}');
}   

這里說一下為什么要替換,首先是es6中編譯字符串中的變量,這個變量必須在scope中,然后,我們的數(shù)據(jù)不可能是就像一個一個的變量,那樣要定義太多,還有就是模板中盡量寫法簡潔。所以這里把簡潔的變量替換為正真的scope中的變量。因為是要動態(tài)替換,所以正則表達式每次都要重新定義(注意轉(zhuǎn)義)。
最后就是如何編譯的問題,因為我們拿到的是個字符串,而es6是要用反引號來編譯,所以這里就需要拼接反引號和字符串進行編譯,大家最容易想到的就是eval,但是介于它可能會帶來一些不可預(yù)知的東西,所以我們使用new Function()的方式。

let str = new Function("return `"+htmlFragment+"`");
root.innerHTML = "";
//這個方法很久之前就有了,并不是最新出的
root.insertAdjacentHTML('afterbegin',str);

3.編譯模板

這里借鑒vue的節(jié)點編譯方式,主要就是對元素節(jié)點和文本節(jié)點的處理。由于并沒有做循環(huán)渲染,所以目前只做了對文本節(jié)點的處理?;镜乃枷脒€是以一顆樹的形式去一層一層的編譯。

    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上看,這個后續(xù)也會加強功能。https://github.com/Stevenzwzhai/plugs/tree/master/es6-template

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,724評論 19 139
  • 一、情景創(chuàng)設(shè)及引入:一分鐘以內(nèi) 二、學(xué)習(xí)目標、重難點呈現(xiàn):兩分鐘以內(nèi) 三、合作學(xué)習(xí)分工及展示評價:兩分鐘以內(nèi) 四、...
    淮高劉溪閱讀 527評論 0 0
  • 自制力即權(quán)利
    阿嚏fairy閱讀 97評論 0 0
  • k
    16de687f9f78閱讀 129評論 0 1
  • 第一章 溝通是一種交流的過程,其參與者處于不同但是有所重疊的背景下,經(jīng)由交換信息而建立關(guān)系,關(guān)系品質(zhì)受外在的、生理...
    宇航讀書閱讀 221評論 0 0

友情鏈接更多精彩內(nèi)容