シンプルなテンプレートエンジンを書きます
ES5は、テンプレート文字列(テンプレートリテラル)をサポートするために始めた、以下の文言をサポートしています。
`string text ${expression} string text`;
実際には、多くのテンプレートエンジンで、多くの場合、同様の構文を使用して、そのような一般的に使用される点として、このようなニーズを持っています
<div>{{=1+2}}</div>
// 或者支持循环或者判断 {{for(var i in it){}}}
<span>{{=i}}</span>
{{}}}
達成するために、単純な補間
基本的なニーズを達成するためにどのようなテンプレートエンジンを見てみましょう、そしてサイクルが判断みなされていない、唯一の変数の操作をサポートしています。
オープンバベル、入力します。
const a = 1;
console.log(`Hi\n${2 + 3}!dk${a}`);
後はBabel
、後で脱出し、あなたが見ることができます
"use strict";
var a = 1;
console.log("Hi\n".concat(2 + 3, "!dk").concat(a));
ことがわかるBabel
補間パラメータが連結に抽出、自己の計算関数のパラメータは、テンプレートリテラルを達成しました。私たちの使用時には、実際には、このような効果を指示していません。
しかし、偽造Babel
プラクティスは、私たちは自分のアイデアを整理することができます:
- そして、解体正の実際の文字列補間して置きます
eval
又はnew Function()
実装補間計算- 連結スプライシングによって、またString.raw使用することができます
コードは次のように実装されています。
var str = "string text ${1 + 2} string text ${2 + 3} test";
function template(str) {
var pattern = /\$\{.*?\}/g;
var patternCapture = /\$\{(.*?)\}/g;
// 将非插值字符串分割出来
var strArr = str.split(pattern);
// 将插值字符串分割出来
var rawArr = str
.match(patternCapture)
.map(item => item.replace(patternCapture, "$1"));
// eval转换
var valueArr = rawArr.map(r => eval(r));
// 使用reduce和concat拼接,
return strArr.reduce(
(acc, curr, index) => acc.concat(curr, valueArr[index] || ""),
""
);
// 或者使用String.raw
// return String.raw({ raw: strArr }, ...valueArr);
}
console.log(template(str));
新機能
上記の使用eval
補間を通常の使用では、実際には、評価されており、eval
それが推奨されていません。そして、では、eval
判断のいくつかを解決するために、条件サイクルが非常に便利ではありません。
だから、次の使用には、new Function()
テンプレート関数を構築します。これに先立ち、我々は説明する必要がnew Function
使用を。
new Function ([arg1[, arg2[, ...argN]],] functionBody)
パラメータが必要な機能の前に渡され、関数の最後のボディ、関数本体は、JavaScript関数定義文の文字列を含んでいます。
第二に、補間が上記に従って実装、我々は一緒に補間及びステッチの計算通常の文字列の後に文字列の連結を使用することができます。
簡単な補間、使用のために{{}}
ラップ、およびステートメント使用して{{~}}
異なります。ここでは簡単な実装があります
function render(tem, data) {
let template = tem;
template = template
.replace(/[\r\n\t]/g, "")
.replace(/\{\{~(.+?)\}\}/g, (_, p1) => {
return '";' + p1 + ' out+="';
})
.replace(/\{\{(.+?)\}\}/g, (_, p1) => {
return '"; out+=""+' + p1 + '+""; out+="';
});
template = 'var out=""; out += "' + template + '";return out;';
var _render = new Function(...Object.keys(data), template);
return _render(...Object.keys(data).map(k => data[k]));
}
var template =
"test array{{~for (var i in group.jobs) {}}{{group.jobs[i]}} {{~}}} test obj {{group.jobs[1]}} {{group.name}} leader是{{leader}}";
var data = {
group: {
name: "group1",
jobs: ["job1", "job2"]
},
leader: "张三"
};
console.log(render(template, data));
テンプレートへのデータの中に注入すると、あなたが使用できるwith(data){}
方法は、私が使用することを好きではないwith
パラメータは分解に渡された後のように。
(終わり)。