翻譯_20行代碼創造JavaScript模板引擎(一)

翻譯_20行代碼創造JavaScript模板引擎(一)

想看博客原文連接,請點擊下方

JavaScript template engine in just 20 linesjavascript


一個很是好用的學習正則表達的網站
正則表達式圖文解說網站html


譯文


事情的原由,我想編寫一個邏輯簡單的模板引擎,它能夠很好知足我如今的需求。java

我知道不能找一些現有的引擎,由於它們絕大多數是基於NodeJS的,很難在瀏覽器中去實現它們。正則表達式

而我但願用原生JavaScript去寫,這樣也能夠在瀏覽器上運行。segmentfault

我是從John Resig的博客[](https://johnresig.com/blog/ja...數組

我稍微改動了一下,縮減到20行。 這個腳本的工做原理,很是有趣。瀏覽器

在本文中, 將一步一步來建立這個引擎,這樣你就體會到來自John的奇思妙想。函數

構思

functiom TemplateEngine(tpl, data) {
    //魔法細節在這裏 magic details here!
}

var tpl = '<p>Hello, my name is <%name%>. I\'m <%age%> years old.</p>';

var data = {
    name: "Shaw",
    age: 18
}

console.log(TemplateEngine(tpl, data)); 
//按照構思,咱們想實現的須要和想獲得結果 應該是 '<p>Hello, my name is Shaw. I'm 18 years old.</p>'

一個簡單的函數,接收兩個參數:tpl(模板字符竄),data(JS對象格式);學習


第一步,匹配參數tpl(模板字符竄)中的動態模塊

動態模塊是指在 tpl(模板字符竄)中,你想要匹配並用數據替換的部分。測試

'<%string%>'

//舉個例子
//tpl中的動態模塊有兩個:<%name%>和<%age%>。

var tpl = '<p>Hello, my name is <%name%>. I\'m <%age%> years old.</p>';

在這裏,我決定用正則表達式去實現,正則表達式不是個人強項,因此有什麼建議,儘管暢所欲言。

Tips: 其實正則沒那麼難,平時多練練就行了。 首先克服心裏的恐懼,嘗試着寫,想不出來,多翻翻基礎知識。

var regEx = /<%([^%>]+)?%>/g

這個正則表達式是什麼意思呢?

若是實在看不懂正則,能夠看下這篇博客。 正則表達式-基礎知識Review

在一個字符竄中,匹配以"<%"開頭 和 "%>" 結尾的字符竄片斷。

g,表示全局匹配。

在這裏,咱們須要用到正則表達式的exec()方法。

該方法用於正則表達式模式在字符竄中運行查找,若是exec()找到匹配的文本,則返回一個數組,不然返回null。

regExp.exec(str);

var tpl = '<p>Hello, my name is <%name%>. I\'m <%age%> years old.</p>';
var regEx =  /<%([^%>]+)?%>/g;

console.log(regEx.exec(tpl));
/*
[0: "<%name%>", 1: "name", index: 21, input: "<p>Hello, my name is <%name%>. I'm <%age%> years old.</p>", length: 2, groups: undefined]
*/

獲得了正則表達式在字符竄中匹配的字符竄片斷。

只獲得一個匹配的字符竄片斷!

但是咱們須要全部匹配的字符竄片斷。

這時,咱們須要一個while循環語句來依次獲得匹配字符竄。

var tpl = '<p>Hello, my name is <%name%>. I\'m <%age%> years old.</p>';

var regEx = /<%([^%>]+)?%>/g;

var match;

while(match = regEx.exec(tpl)) {

    console.log(match);

    //["<%name%>", "name", index: 21, input: "<p>Hello, my name is <%name%>. I'm <%age%> years old.</p>", groups: undefined]

    //["<%age%>", "age", index: 35, input: "<p>Hello, my name is <%name%>. I'm <%age%> years old.</p>", groups: undefined]
}

這裏要了解RegExp.exec()方法,在全局匹配中的特性:

調用全局的RegExp對象的exec()時,它會在RegExp實例的lastIndex屬性指定的字符處開始檢索字符竄string

當exec()找到了與表達式相匹配的文本時, 在匹配後, 它將把RegExp實例的lastIndex屬性設置爲匹配文本的最後一個字符的下一個位置。能夠經過反覆調用exec()方法來遍歷字符竄中的全部匹配文本。

==當exec()再也找不到匹配的文本時,它將返回null,並把lastIndex屬重置爲0。==

var reg = /\d/g;

var r =  reg.exec('a1b2c3');

console.log(r);

console.log(reg.lastIndex); // 2

r = reg.exec('a1b2c3');

console.log(reg.lastIndex); // 4
var reg = /\d/g;

while (r = reg.exec('a1b2c3')) {
    console.log(r.index + ':' + r[0])
}

//1:1 , 3:2, 5:3

第二步,用數據替換在模板中匹配的字符竄片斷

如今,變得有趣了!!

給函數傳遞一個真實的數據(JS對象格式)。

而後用數據替換匹配的字符竄片斷。

能想到的最簡單的方法,就是使用String.prototype.replace()方法了。

咱們能夠這樣寫

function TemplateEngine(tpl, data){
    var regEx = /<%([^%>]+)?%>/g, matchStrArr;

    while(matchStrArr = regEx.exec(tpl)) {
        tpl = tpl.replace(matchStrArr[0], data[matchStrArr[1]])
    }

    return tpl;
}

var tpl = '<p>Hello, my name is <%name%>. I\'m <%age%> years old.</p>';

var personalInfo = {
    name: "Shaw",
    age: 18
}

var htmlStr = TemplateEngine(tpl, personalInfo);

console.log(htmlStr); // <p>Hello, my name is Shaw. I'm 18 years old.</p>

//運行成功,可使用。

測試,運行成功!

可是這還不夠好,數據是很是簡單的JS對象,使用object['property']對象的中括號語法,很容易去讀取對象的值。

但在實踐中,咱們用到的數據中,可能有複雜的嵌套對象。

//嵌套對象
data = {
    name: "Krasimir Tsonev",
    profile: {age:29}
}
相關文章
相關標籤/搜索