js模板引擎渐进--处理需要输出 { 或者 } 的情况(8)

 

到目前为止,我们前面写的 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>

 

下一篇我们来改进这些代码

 

目录:

js模板引擎渐进--前言

js模板引擎渐进--区别js代码和html字符串(1)

js模板引擎渐进--生成最简单的function(2)

js模板引擎渐进--区别js代码和html字符串2(3)

js模板引擎渐进--改进字符串拼接方式(4)

js模板引擎渐进--each/for(5)

js模板引擎渐进--each改进(6)

js模板引擎渐进--if/else(7)

js模板引擎渐进--处理需要输出 { 或者 } 的情况(8)

js模板引擎渐进--代码改进封装(9)

js模板引擎渐进--后记

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值