在拼接字符串时,我以前基本用+来进行拼接;当遇到很长的字符串,且需要拼接的点很多时,代码就很复杂容易搞错,而且很不美观。于是我想到了能不能像angular和vue处理html元素一样用{{param}}进行绑定,就像下面的代码:
var OUT_IMAGE_VIEW = 'http://localhost:8088/image/exitStation.jpg', EXIT_STATIONAME = '长沙西'; '<a class="fancybox" href="{{OUT_IMAGE_VIEW}}" title="出口收费站:{{EXIT_STATIONAME}}">'
OUT_IMAGE_VIEW和EXIT_STATIONAME为变量,通过我的方法这些变量将自动拼接到字符串里面。输出的结果字符串为:
'<a class="fancybox" href="http://localhost:8088/image/exitStation.jpg" title="出口收费站:长沙西">'
到这里,我心里在想,像这种方法肯定有很多前辈写出来了,或者某种框架插件里面能实现这种字符串的处理。不管那么多,我先百度一把,于是找到了它:http://www.jb51.net/article/79311.htm。一看完全符合我的胃口,接下来我就做我最拿手的活了:copy代码
function render(template, context) { var tokenReg = /(\\)?\{([^\{\}\\]+)(\\)?\}/g; return template.replace(tokenReg, function (word, slash1, token, slash2) { if (slash1 || slash2) { return word.replace('\\', ''); } var variables = token.replace(/\s/g, '').split('.'); var currentObject = context; var i, length, variable; for (i = 0, length = variables.length, variable = variables[i]; i < length; ++i) { currentObject = currentObject[variable]; if (currentObject === undefined || currentObject === null) return ''; } return currentObject; }) } String.prototype.render = function (context) { return render(this, context); };
然后喜滋滋用它里面的测试代码测试一把:
"{greeting}! My name is { author.name }.".render({ greeting: "Hi", author: { name: "hsfzxjy" } }); // Hi! My name is hsfzxjy.
结果发现,然并卵,输出来的是:
问题不大,就是author.name没有解析,整体思路和逻辑肯定没问题。到这里我就只能单步调试看看能不能找出它的问题咯,看着他的文章开始我的研究。经过我一顿操作,发现问题出在for循环时,i取值的问题,variable = variables[i]没有随循环运行,所以一直取得variables[0]的值。修改后的代码:
String.prototype.render = function(context) { var tokenReg = /(\\)?\{([^\{\}\\]+)(\\)?\}/g; return this.replace(tokenReg, function(word, slash1, token, slash2) { if (slash1 || slash2) { return word.replace('\\', ''); } var variables = token.replace(/\s/g, '').split('.'); var currentObject = context; var i, length; for (i = 0, length = variables.length; i < length; ++i) { currentObject = currentObject[variables[i]]; if (currentObject === undefined || currentObject === null) return ''; } return currentObject; }); };
测试结果:
成功,可是,又遇到了问题,这个方法只支持对象,不支持数组,而我的数据源是对象数组,我要实现的效果像这样:
var stringFmt = { out: { OUT_IMAGE_VIEW: 'http://localhost:8088/image/exitStation.jpg', EXIT_STATIONAME: '长沙西' } point: [{ POINT_IMAGE_VIEW: 'http://localhost:8088/image/pointStation1.jpg', POINT_STATIONAME: '益阳' }, { POINT_IMAGE_VIEW: 'http://localhost:8088/image/pointStation2.jpg', POINT_STATIONAME: '衡阳' }] } '<a class="fancybox" href="{out.OUT_IMAGE_VIEW}" title="出口收费站:{out.EXIT_STATIONAME}">' '<a class="fancybox" href="{point[0].POINT_IMAGE_VIEW}" title="识别收费站1:{point[0].POINT_STATIONAME}">' '<a class="fancybox" href="{point[1].POINT_IMAGE_VIEW}" title="识别收费站2:{point[1].POINT_STATIONAME}">'
又开始我的研究,最终代码如下:
// 字符串模板匹配 String.prototype.render = function(context) { var tokenReg = /(\\)?\{([^\{\}\\]+)(\\)?\}/g; return this.replace(tokenReg, function(word, slash1, token, slash2) { if (slash1 || slash2) { return word.replace('\\', ''); } var variables = token.replace(/\s/g, '').split('.'); var currentObject = context; var i, length; for (i = 0, length = variables.length; i < length; ++i) { var curVariables = variables[i].split('['); // 用`[`进行字符串分割 a[0][1] → ["a", "0]", "1]"] currentObject = currentObject[curVariables[0]]; // 第一位是数组名 if (curVariables.length > 1) { // 如果大于1,则有`[`符号,就是数组对象 curVariables.shift(); // 去掉数组名,循环["0]", "1]"] curVariables.forEach(function(item) { currentObject = currentObject[parseInt(item.substr(0, 1))]; // 用数组的索引取值 }); } if (currentObject === undefined || currentObject === null) return ''; } return currentObject; }); };
第一次写博客,感觉有点啰嗦,哈哈,不知道这样实现合不合理,至少我实现了我想要的,继续加油!!