国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

翻譯_只需20行代碼創(chuàng)造JavaScript模板引擎(二)

superw / 1829人閱讀

摘要:函數(shù)執(zhí)行后應(yīng)該返回最終編譯的模板。到了這里,我們只需要?jiǎng)?chuàng)建函數(shù)并執(zhí)行它。

上文鏈接翻譯_只需20行代碼創(chuàng)造JavaScript模板引擎(一)

但是這還不夠好,數(shù)據(jù)是非常簡單的對(duì)象,并且很容易使用object["property"]對(duì)象的中括號(hào)語法,去讀取對(duì)象的值。

但在實(shí)踐中,我們用到的數(shù)據(jù)中,可能有復(fù)雜的嵌套對(duì)象。

//嵌套對(duì)象
data = {
    name: "Krasimir Tsonev",
    profile: {age:29}
}

如果有復(fù)雜的嵌套對(duì)象,就不能用對(duì)象的中括號(hào)語法讀取值了。

所以String.prototype.replace(matchedStr, data["profile.age"]) 就行不通了。

因?yàn)閐ata["profile.age"],每次返回undefined。

//對(duì)象的中括號(hào)語法讀取值 object["property"]

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

console.log(obj["name"]); //"Shaw"
console.log(obj["age"]); // 18  


//復(fù)雜的嵌套對(duì)象,就不能用對(duì)象的中括號(hào)語法讀取值了。

var obj = {
    name: "Shaw",
    profile: {
        age: 18
    }
}

console.log(obj["profile.age"]); // undefined

那么,怎么解決這個(gè)問題?
最好的辦法是在模板中<%和%>之間放置真正的JavaScript代碼。

var tpl = "

Hello, my name is <%this.name%>. I"m <%this.profile.age%> years old.

";

這怎么可能呢? John使用了new Function()語法, 沒有顯式的聲明函數(shù)。

var fn = new Function("arg", "console.log(arg+1);");
fn(2); // 3

//fn是一個(gè)可以傳入一個(gè)參數(shù)的函數(shù)
//fn函數(shù)體內(nèi)的語句,就是 console.log(arg+1);

/* 等價(jià)于*/

function fn(arg) {
    console.log(arg +1);
}

fn(2); //3

我們可以利用這個(gè)語法,在一行代碼中,定義函數(shù)、參數(shù)和函數(shù)體。這正是我們需要的。

在利用這種語法,創(chuàng)建函數(shù)之前。

我們必須設(shè)計(jì)好,函數(shù)體怎么寫。函數(shù)執(zhí)行后應(yīng)該返回最終編譯的模板。

回想一下,我們經(jīng)常使用的字符竄拼接方法。

"

Hello, my name is " + this.name + ". I"m" + this.profile.age + " years old.

";

這說明,我們可以把字符竄模板里面的內(nèi)容拆解,拆解為html和JavaScript代碼。

一般情況下,我們都是使用for循環(huán)去遍歷數(shù)據(jù)。

// 傳入的字符竄模塊
var template =
"My Skill:" +
"<%for(var index in this.skills) {%>" +
"<%this.skills[index]%>" +
"<%}%>";
// 預(yù)想的返回結(jié)果

return 
"My skills:" +
for(var index in this.skills) { +
"" +
this.skills[index] +
"" +
}

當(dāng)然,這將產(chǎn)生一個(gè)錯(cuò)誤。這就是為什么我決定遵循約翰文章中使用的邏輯,把所有的字符串放到一個(gè)數(shù)組中。

var r = [];
r.push("My skills:");
for(var index in this.skills) {
    r.push("");
    r.push(this.skills[index]);
    r.push("");
}
return r.join("");

下一個(gè)邏輯步驟是收集定制生成函數(shù)的不同行。
我們已經(jīng)從模板中提取了一些信息。我們知道占位符的內(nèi)容和它們的位置。所以,通過使用一個(gè)輔助變量(游標(biāo))

function TemplateEngine(tpl, data) {

    var tplExtractPattern = /<%([^%>]+)?%>/g,
        code = "var r=[];
",
        cursor = 0,
        match;

    function addCode(line) {
        code += "r.push("" + line.replace(/"/g,""") +""); 
";
    }

    while(match = tplExtractPattern.exec(tpl)) {
        addCode(tpl.slice(cursor, match.index));
        addCode(match[1]);
        cursor = match.index + match[0].length;
    }

    code += "return r.join("");";

    console.log(code);

    return tpl;

}

var template = "

Hello, my name is <%this.name%>. I"m <%this.profile.age%> years old.

"; TemplateEngine(template, { name: "Shaw", profile: { age: 18 } });

變量code保存著函數(shù)體的代碼。
在while循環(huán)語句中,我們也需要變量cursor游標(biāo),告訴我們字符竄slice()方法截取的起始坐標(biāo)和末尾坐標(biāo)。
變量code在while循環(huán)語句中,不斷的拼接。

但是code的最終結(jié)果是

/*
var r=[];
r.push("

Hello, my name is "); r.push("this.name"); r.push(". I"m "); r.push("this.profile.age"); return r.join("");

Hello, my name is <%this.name%>. I"m <%this.profile.age%> years old.

*/

這不是我們想要的。 "this.name" 和 "this.profile.name" 不應(yīng)該被引號(hào)包裹。

所以我們需要addCode函數(shù)做一個(gè)小小的改動(dòng)

function TemplateEngine(tpl,data){

    var tplExtractPattern = /<%([^%>]+)?%>/g,
        code = "var r=[];
",
        cursor = 0,
        match;

    function addCode(line, js) {
        if(js) {
            code += "r.push(" + line + ");
";
        } else {
            code += "r.push("" + line.replace(/"/g,""") + "");
";
        }
    }

    while(match = tplExtractPattern.exec(tpl)) {
        addCode(tpl.slice(cursor, match.index));
        addCode(match[1], true);
        cursor = match.index + match[0].length;
    }

    code += "return r.join("");";

    console.log(code);

    return tpl;

}

var template = "

Hello, my name is <%this.name%>. I"m <%this.profile.age%> years old.

"; TemplateEngine(template, { name: "Shaw", profile: { age: 18 } });

現(xiàn)在this可以正確指向執(zhí)行對(duì)象了。

var r=[];
r.push("

Hello, my name is "); r.push(this.name); r.push(". I"m "); r.push(this.profile.age); return r.join("");

到了這里,我們只需要?jiǎng)?chuàng)建函數(shù)并執(zhí)行它。
在TemplateEngine函數(shù)里把return tpl 替換成

return new Function(code.replace(/[
	
]/g, "")).apply(data);

我們不需要傳入?yún)?shù),這里我使用apply()方法,改變了作用域,現(xiàn)在this.name指向了data。

幾乎已經(jīng)完成了。但是我們還需要支持更多JavaScript關(guān)鍵字,比如if/else,循環(huán)流程語句。
讓我們從相同的例子,再次進(jìn)行構(gòu)思。

function TemplateEngine(tpl,data){

    var tplExtractPattern = /<%([^%>]+)?%>/g,
        code = "var r=[];
",
        cursor = 0,
        match;

    function addCode(line, js) {
        if(js) {
            code += "r.push(" + line + ");
";
        } else {
            code += "r.push("" + line.replace(/"/g,""") + "");
";
        }
    }

    while(match = tplExtractPattern.exec(tpl)) {
        addCode(tpl.slice(cursor, match.index));
        addCode(match[1], true);
        cursor = match.index + match[0].length;
    }

    code += "return r.join("");";

    console.log(code);

    return new Function(code.replace(/[	
	]/g, "")).apply(data);
}

var template = 
"My skill:" +
"<%for(var index in this.skills) {%>" +
"<%this.skills[index]%>" +
"<%}%>";

TemplateEngine(template, {
    skills: ["js", "html", "css"]
}); 
// Uncaught SyntaxError: Unexpected token for

調(diào)用TemplateEngine(),控制臺(tái)報(bào)錯(cuò)了,Uncaught SyntaxError: Unexpected token for。
在控制臺(tái)打印出,拼接的代碼

var r=[];
r.push("My skill:");
r.push(for(var index in this.skills) {);
r.push("");
r.push(this.skills[index]);
r.push("");
r.push(});
return r.join("");

帶有for循環(huán)的語句不應(yīng)該被直接放到數(shù)組里面,而是應(yīng)該作為腳本的一部分直接運(yùn)行。所以在把代碼語句添加到code變量之前還要多做一個(gè)判斷。

var re = /<%([^%>]+)?%>/g,
    reExp = /(^( )?(if|for|else|switch|case|break|{|}))(.*)?/g,
    code = "var Arr = [];
",
    cursor = 0;

function addCode(line,js) {
    if(js){
        if(line.match(reExp)) {
            code += line +"
";
        } else {
            code += "r.push(" + line + ");
";
        }
    } else {
        code += "r.push("" + line.replace(/"/g,""")) + "");
";
    }
}

添加一個(gè)新的正則表達(dá)式。它會(huì)判斷代碼中是否包含if、for、else等關(guān)鍵字。
如果有的話就直接添加到腳本代碼中去,否則就添加到數(shù)組中去。

function TemplateEngine(tpl,data){

    var tplExtractPattern = /<%([^%>]+)?%>/g,
    jsExtractReExp = /(^( )?(if|for|else|switch|case|break|{|}))(.*)?/g,
    code = "var arr = [];
",
    cursor = 0,
    match;

    function addCode(line,js) {
        if(js){
            if(line.match(jsExtractReExp)) {
                code += line +"
";
            } else {
                code += "arr.push(" + line + ");
";
            }
        } else {
            code += "arr.push("" + line.replace(/"/g,""") + "");
";
        }
    }


    while(match = tplExtractPattern.exec(tpl)) {
        addCode(tpl.slice(cursor, match.index));
        addCode(match[1], true);
        cursor = match.index + match[0].length;
    }

    code += "return arr.join("");";

    console.log(code);

    return new Function(code.replace(/[	
	]/g, "")).apply(data);
}

var template = 
"My skill:" +
"<%for(var index in this.skills) {%>" +
"<%this.skills[index]%>" +
"<%}%>";

TemplateEngine(template, {
    skills: ["js", "html", "css"]
});


/*
var arr = [];
arr.push("My skill:");
for(var index in this.skills) {
arr.push("");
arr.push(this.skills[index]);
arr.push("");
}
return arr.join("");
*/

//"My skill:jshtmlcss"

一切都是正常編譯的 :)。

最后的修改,實(shí)際上給了我們更強(qiáng)大的處理能力。

我們可以直接將復(fù)雜的邏輯應(yīng)用到模板中。例如

var template = 
"My skills:" + 
"<%if(this.showSkills) {%>" +
    "<%for(var index in this.skills) {%>" + 
    "<%this.skills[index]%>" +
    "<%}%>" +
"<%} else {%>" +
    "

none

" + "<%}%>"; console.log(TemplateEngine(template, { skills: ["js", "html", "css"], showSkills: true })); /* var arr = []; arr.push("My skills:"); if(this.showSkills) { arr.push(""); for(var index in this.skills) { arr.push(""); arr.push(this.skills[index]); arr.push(""); } arr.push(""); } else { arr.push("

none

"); } return arr.join(""); */ //"My skills:jshtmlcss"

最后,我進(jìn)一步做了一些優(yōu)化,最終版本如下

var TemplateEngine = function(templateStr, data) {
    var tplStrExtractPattern = /<%([^%>]+)?%>/g,
        jsKeyWordsExtractPattern = /(^( )?(for|if|else|swich|case|break|{|}))(.*)?/g,
        code = "var arr = [];
",
        cursor = 0,
        match;
    var addCode = function(templateStr, jsCode) {
        if(jsCode) {
            if(templateStr.match(jsKeyWordsExtractPattern)) {
                code += templateStr + "
";
            } else {
                code += "arr.push(" + templateStr + ");
";
            }
        } else {
            code += "arr.push("" + templateStr.replace(/"/g, """) + "");
";
        }
    }
    while(match = tplStrExtractPattern.exec(templateStr)){
        addCode(templateStr.slice(cursor, match.index));
        addCode(match[1], true);
        cursor = match.index + match[0].length;
    }
    code += "return arr.join("");";
    return new Function(code.replace(/[
	]/g, "")).apply(data);
}

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/98678.html

相關(guān)文章

  • 淺談web中前端模板引擎的使用

    摘要:置換型模板引擎的優(yōu)點(diǎn)實(shí)現(xiàn)簡單,缺點(diǎn)效率低,無法滿足高負(fù)載的應(yīng)用請(qǐng)求。用途百度詞條模板引擎可以讓網(wǎng)站程序?qū)崿F(xiàn)界面與數(shù)據(jù)分離,業(yè)務(wù)代碼與邏輯代碼的分離,提升開發(fā)效率,良好的設(shè)計(jì)也提高了代碼的復(fù)用性。前端模板的出現(xiàn)使得前后端分離成為可能。 模板引擎 模板引擎-百度詞條 什么是模板引擎?(百度詞條) 模板引擎(這里特指用于Web開發(fā)的模板引擎)是為了使用戶界面與業(yè)務(wù)數(shù)據(jù)分離而產(chǎn)生的,它可以生成...

    妤鋒シ 評(píng)論0 收藏0
  • 翻譯_20代碼創(chuàng)造JavaScript模板引擎(一)

    摘要:翻譯行代碼創(chuàng)造模板引擎一想看博客原文鏈接,請(qǐng)點(diǎn)擊下方一個(gè)非常好用的學(xué)習(xí)正則表達(dá)的網(wǎng)站正則表達(dá)式圖文解說網(wǎng)站譯文事情的起因,我想編寫一個(gè)邏輯簡單的模板引擎,它可以很好滿足我現(xiàn)在的需求。,表示全局匹配。 翻譯_20行代碼創(chuàng)造JavaScript模板引擎(一) 想看博客原文鏈接,請(qǐng)點(diǎn)擊下方 JavaScript template engine in just 20 lines 一個(gè)非常好用...

    hiyang 評(píng)論0 收藏0
  • 小型的編程項(xiàng)目有哪些值得推薦?這本神書寫了 22 個(gè),個(gè)個(gè)了不得

    摘要:電子表格使用語言電子表格是辦公軟件的必備,我們最熟知的是微軟的。文中用框架來實(shí)現(xiàn)一個(gè)簡單的電子表格,所用代碼僅行。 showImg(https://segmentfault.com/img/remote/1460000019770011); 本文原創(chuàng)并首發(fā)于公眾號(hào)【Python貓】,未經(jīng)授權(quán),請(qǐng)勿轉(zhuǎn)載。 原文地址:https://mp.weixin.qq.com/s/Ob... 今天,...

    haitiancoder 評(píng)論0 收藏0
  • 小型的編程項(xiàng)目有哪些值得推薦?這本神書寫了 22 個(gè),個(gè)個(gè)了不得

    摘要:電子表格使用語言電子表格是辦公軟件的必備,我們最熟知的是微軟的。文中用框架來實(shí)現(xiàn)一個(gè)簡單的電子表格,所用代碼僅行。 showImg(https://segmentfault.com/img/remote/1460000019770011); 本文原創(chuàng)并首發(fā)于公眾號(hào)【Python貓】,未經(jīng)授權(quán),請(qǐng)勿轉(zhuǎn)載。 原文地址:https://mp.weixin.qq.com/s/Ob... 今天,...

    Bowman_han 評(píng)論0 收藏0
  • 小型的編程項(xiàng)目有哪些值得推薦?這本神書寫了 22 個(gè),個(gè)個(gè)了不得

    摘要:電子表格使用語言電子表格是辦公軟件的必備,我們最熟知的是微軟的。文中用框架來實(shí)現(xiàn)一個(gè)簡單的電子表格,所用代碼僅行。 showImg(https://segmentfault.com/img/remote/1460000019770011); 本文原創(chuàng)并首發(fā)于公眾號(hào)【Python貓】,未經(jīng)授權(quán),請(qǐng)勿轉(zhuǎn)載。 原文地址:https://mp.weixin.qq.com/s/Ob... 今天,...

    sf_wangchong 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<