到目前为止,我们前面写的 template 函数已经可以在大多数场景使用了。然而,有一种情况,我们也可能会常用----输出 {}。
而从之前的代码我们知道,我们正是通过 {} 来区分 代码字符串和html内容字符串的, {} 的内容还可以根据一定的规则解析出 each/if/else 等指令,那假如,我们想要输出的 html 包含 {} 呢??
这是一个棘手的问题,但,棘手归棘手,总要解决的。
下面我们一起来思考如何解决这个问题。
一开始以来,我们都是 单花括号 {} 来区分代码区域的,而博主看到的有些模板引擎使用的 是 双花括号 {{}} 来标识代码内容 (这部分想不明白为什么要这样子,可能自己没遇到 单花括号 {} 带来的局限性),既然已经在用了 {} ,那我们就不需要改了。
在 这个 template 系列中我们说过,我们之所以能够根据模板生成我们想要的 function 是因为有规则的存在,我们制定的规则我们来解析,如此而已。那么对于 需要 输出 {} 这种情况,我们设定:
1.遇到两个 { 即 {{ 时,我们就输出 "{" ,即当作内容字符串看待。
2.遇到两个 } 即 }} 时,我们就输出 "}" ,即当作内容字符串看待。
定下了规则后
1.我们需要分析当有多个连续的 { 或 } 时,我们怎么处理呢?
方案:这个“多个” 可以当作一个奇偶问题来处理,无论多少,如果是奇数的话,则也只有一个 {或者} 当作 代码内容和原文内容的分割者,所以我们只需要将 { 或者 } 的数量取余(N % 2),如果余数为 1 ,则有一个 { 或者 },否则,原文输出 一般数量(N / 2)的 "{" 或者 "}"
2. { 或者 } 的数量如何统计以及处理呢?
方案:原先我们的处理是遍历一个个字符,然后判断 处理,再一个个拼起来,其实,除了 { 或者 } 现在要进行一个特殊处理,其它的字符处理仍然是按照我们原先的处理方式即可,所以,在处理 template 拆出来的每一个字符 value,我们先区分为两种情况:
a. value == '{' || value == '}'
b. value 等于其它
但不管什么情况,最后也是要走到我们前面写的 template 函数里的 switch 里进行判断处理。
那么,我么现在来详细解析一下 a,b 这两种情况下分别要做什么处理。
为了记录 { 或者 } 的数量,博主使用 brace 来记录 "{"或者"}",用 bracecount 来记录 brace 所代表的值的数量(为什么 只用一个 brace 来记录 "{"或者"}" 呢?因为,我们要处理的是 “连续” 的 { 或者 } ,所以,只要 template 拆出来的每一个字符 value 的值只要变了,那就是说明连续到这里就断了,那就可以对 变之前的 符号进行处理,然后对新的 brace 进行重新统计)。
1.对于 a 情况,我们的处理如下:
1.1 如果 template 拆出来的每一个字符 value 与现有的 brace 的值一样,则只需要累积 bracecount 这个总数
1.2 否则,根据 bracecount 这个总数的奇偶情况处理处理,处理完之后对新的 brace 重新记录 bracecount
2.对于 b 情况,我们要判断 bracecount 是否大于 0,是的话,要根据这个数的奇偶情况处理即可。
为了服用某些重复的代码,我们将对代码做一些调整:
比如类似这段代码,在之前的我们就有多个地方有类似的判断了
if (isvarcode) {
varcode.push(" ")
}
else {
tempcode.push(" ");
}
所以我们调整一下:
var handlerPushValue = function (value) {
if (isvarcode) {
varcode.push(value.replace("\\\"","\""))
}
else {
tempcode.push(value);
}
}
ps: varcode 把 转义后的引号不转回来的话,会导致 js 代码内容变成字符串原样处理
同时,我们将 switch 这段代码也抽出来,这部分也会复用到:
var handlerSwitch = function (switchvalue) {
//console.log(value);
switch (switchvalue) {
case "\n":
handlerPushValue(" ");
break;
case "\"":
handlerPushValue("\\\"");
break;
case "{":
isvarcode = true;
resultcode.push(" result.push(\"" + tempcode.join("") + "\") ;");
tempcode = [];
break;
case "}":
isvarcode = false;
var varvalue = varcode.join("");
if (varvalue.indexOf("each") == 0) {
// each index,value arr
var eachInfo = varvalue.split(' ');
if (eachInfo.length != 3) throw "each 参数无效:each index,value arr";
var itemInfo = eachInfo[1].split(',');
if (itemInfo.length != 2) throw "each 参数无效:each index,value arr";
resultcode.push("for (var " + itemInfo[0] + " in " + eachInfo[2] + ") {var " + itemInfo[1] + " = " + eachInfo[2] + "[" + itemInfo[0] + "];");
}
else if (varvalue === "/each") {
resultcode.push(" }");
}
else if (varvalue.indexOf("if") == 0) {
var ifInfo = varvalue.split(" ");
resultcode.push("if(" + ifInfo[1] + "){");
}
else if (varvalue.indexOf("else-if") == 0) {
var ifInfo = varvalue.split(" ");
resultcode.push(" } else if(" + ifInfo[1] + "){");
}
else if (varvalue.indexOf("else") == 0) {
var ifInfo = varvalue.split(" ");
resultcode.push(" } else {");
}
else if (varvalue.indexOf("/if") == 0) {
resultcode.push(" }");
}
else {
resultcode.push(" result.push(" + varvalue + ") ;");
}
varcode = [];
break;
default:
handlerPushValue(switchvalue);
}
}
模板代码:
<h3>33{{{data.value+"{{}}"}32}}23</h3>
目标代码:
function func(data) {
var result=[];
result.push(" <h3>33{") ;
result.push(data.value+"{}") ;
result.push("32}23</h3> ") ;
return result.join("");
}
实现代码(完整函数):
function Template2code(template) {
var resultcode = [];
resultcode.push("function func(data) { var result=[];");
var tempcode = [];
var varcode = [];
var isvarcode = false;
var eachIndex = 0;
var brace = "";
var bracecount = 0;
var handlerPushValue = function (value) {
if (isvarcode) {
varcode.push(value.replace("\\\"","\""))
}
else {
tempcode.push(value);
}
}
var handlerSwitch = function (switchvalue) {
//console.log(value);
switch (switchvalue) {
case "\n":
handlerPushValue(" ");
break;
case "\"":
handlerPushValue("\\\"");
break;
case "{":
isvarcode = true;
resultcode.push(" result.push(\"" + tempcode.join("") + "\") ;");
tempcode = [];
break;
case "}":
isvarcode = false;
var varvalue = varcode.join("");
if (varvalue.indexOf("each") == 0) {
// each index,value arr
var eachInfo = varvalue.split(' ');
if (eachInfo.length != 3) throw "each 参数无效:each index,value arr";
var itemInfo = eachInfo[1].split(',');
if (itemInfo.length != 2) throw "each 参数无效:each index,value arr";
resultcode.push("for (var " + itemInfo[0] + " in " + eachInfo[2] + ") {var " + itemInfo[1] + " = " + eachInfo[2] + "[" + itemInfo[0] + "];");
}
else if (varvalue === "/each") {
resultcode.push(" }");
}
else if (varvalue.indexOf("if") == 0) {
var ifInfo = varvalue.split(" ");
resultcode.push("if(" + ifInfo[1] + "){");
}
else if (varvalue.indexOf("else-if") == 0) {
var ifInfo = varvalue.split(" ");
resultcode.push(" } else if(" + ifInfo[1] + "){");
}
else if (varvalue.indexOf("else") == 0) {
var ifInfo = varvalue.split(" ");
resultcode.push(" } else {");
}
else if (varvalue.indexOf("/if") == 0) {
resultcode.push(" }");
}
else {
resultcode.push(" result.push(" + varvalue + ") ;");
}
varcode = [];
break;
default:
handlerPushValue(switchvalue);
}
}
for (var key in template) {
var value = template[key];
//if(value=='2') debugger;
//var switchvalue = "";
if (value == '{' || value == '}') {
if (brace == "") {
brace = value;
bracecount = 1;
}
else {
if (brace === value) {
bracecount++;
}
else {
var remainder = bracecount % 2;
if (remainder == 1) {
// bracecount/2 次的插入
for (var i = 0; i < parseInt(bracecount / 2); i++) {
handlerPushValue(brace);
}
handlerSwitch(brace)
}
else {
// bracecount/2 次的插入
for (var i = 0; i < parseInt(bracecount / 2); i++) {
handlerPushValue(brace);
}
}
brace = value;
bracecount = 1;
}
}
}
else {
if (bracecount == 0) {
handlerSwitch(value)
}
else {
//这里除了要处理 {} 还要继续把 当前值进行处理
var remainder = bracecount % 2;
if (remainder == 1) {
// bracecount/2 次的插入
for (var i = 0; i < parseInt(bracecount / 2); i++) {
handlerPushValue(brace);
}
handlerSwitch(brace)
}
else {
// bracecount/2 次的插入
for (var i = 0; i < parseInt(bracecount / 2); i++) {
handlerPushValue(brace);
}
}
handlerSwitch(value)
brace = "";
bracecount = 0;
}
}
}
resultcode.push(" result.push(\"" + tempcode.join("") + "\") ;");
tempcode = [];
resultcode.push("return result.join(\"\");}")
return resultcode.join("");
}
传入数据:
var data = {
value: 3
}
渲染结果:
<h3>33{3{}32}23</h3>
下一篇我们来改进这些代码
目录: