轻量级模板系统
开发问卷系统时,开发了一个简单的模板管理功能。实现了简单的变量替换、循环、自定义函数、并提供了循环变量tmCount(从0开始)和tmNumber(从1开始)。不多说,先上代码:
var templates = {},
tmp,
supplant = {
init: function (str, params) {
var value, prop, tmp, len;
for (prop in params) {
if (params.hasOwnProperty(prop)) {
value = params[prop];
switch (Object.prototype.toString.call(value)) {
case '[object Number]':
case '[object String]':
tmp = {};
tmp[prop] = value;
str = supplant.replaceString(str, tmp);
break;
case '[object Function]':
str = supplant.replaceFunc(str, prop, value, params);
break;
case '[object Array]':
str = supplant.replaceArray(str, prop, value);
break;
default:
break;
}
}
}
return str;
},
replaceString: function (str, params) {
var prop;
for (prop in params) {
if (params.hasOwnProperty(prop)) {
str = str.split('{' + prop + '}').join(params[prop]);
}
}
return str;
},
replaceFunc: function (str, prop, func, item) {
return str.split('{' + prop + '}').join(func(item));
},
replaceArray: function (str, prop, data) {
var i = 0,
left,
middle,
right,
s = '{#' + prop + '}',
e = '{/' + prop + '}',
len = data.length,
start = 0,
end = 0;
start = str.indexOf(s);
end = str.indexOf(e, start);
left = str.slice(0, start);
middle = str.slice(start + s.length, end);
right = str.slice(end + e.length);
if (len > 0 && start > -1) {
for (; i < len; ++i) {
data[i].tmCount = i;
data[i].tmNumber = i + 1;
if (data[i].content !== null) { //如果content属性不等于null
left += supplant.init(middle, data[i]);
} else {
left += data[i].replace;
}
}
str = left + right;
if (str.indexOf(s) > -1) {//如果包括多个循环
str = supplant.replaceArray(str, prop, data);
}
}
if (len == 0 && start > -1) {
str = left + right;
}
return str;
}
};
return {
render: function (name, params) {
if (typeof templates[name] !== 'string') {
throw 'Template ' + name + ' not found!';
}
tmp = name;
return supplant.init(templates[name], params);
},
defineTemplate: function (name, template) {
if (typeof template == 'string') {
templates[name] = template;
} else { //数组
templates[name] = template.join('');
}
}
};
})();
上面代码中定义一个templateManager对象用来管理模板,提供了两个接口:
- defineTemplate 用来定义模板
- render 用来渲染模板
内部私有的supplant对象实现模板引擎,提供了替换变量、替换循环、替换函数的功能。
文档和示例:
templateManager.defineTemplate('profile', '姓名:{name},blog:{blog}');
templateManager.render('profile', {name: 'vapour', blog: 'http://dovapour.info/'});
//结果 姓名:vapour,blog:http://dovapour.info/
//实现循环
templateManager.defineTemplate('website', [
'<ul>',
'{#webs}<li><a href="{url}">{name}<_buff_29_buff_li>{/webs}',
'<ul>'
]);
templateManager.render('website', {
webs: [{
name: '百度',
url: 'http://www.baidu.com/',
getLen: function (item) {
return item.url.length;
}
}, {
name: '淘宝',
url: 'http://www.taobao.com/',
getLen: function (item) {
return item.url.length;
}
}, {
name: '腾讯',
url: 'http://www.qq.com/',
getLen: function (item) {
return item.url.length;
}
}, {
name: '网易',
url: 'http://163.com/',
getLen: function (item) {
return item.url.length;
}
}, {
name: '新浪',
url: 'http://www.sina.com/',
getLen: function (item) {
return item.url.length;
}
}]
});
/*
<ul>
<li><a href="http://www.baidu.com/">百度</a>,url长度21</li>
<li><a href="http://www.taobao.com/">淘宝</a>,url长度22</li>
<li><a href="http://www.qq.com/">腾讯</a>,url长度18</li>
<li><a href="http://163.com/">网易</a>,url长度15</li>
<li><a href="http://www.sina.com/">新浪</a>,url长度20</li>
<ul>
*/