在拼接字符串时,我以前基本用+来进行拼接;当遇到很长的字符串,且需要拼接的点很多时,代码就很复杂容易搞错,而且很不美观。于是我想到了能不能像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;
});
};
第一次写博客,感觉有点啰嗦,哈哈,不知道这样实现合不合理,至少我实现了我想要的,继续加油!!