mirror of https://github.com/layui/layui
新增 laytpl 局部自定义标签符功能,并优化整体代码
parent
3619aabbc8
commit
82a811b8ad
|
@ -1,27 +1,18 @@
|
||||||
/**
|
/**
|
||||||
* laytpl 模板引擎
|
* laytpl 轻量模板引擎
|
||||||
*/
|
*/
|
||||||
|
|
||||||
layui.define(function(exports){
|
layui.define(function(exports){
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
|
// 默认属性
|
||||||
var config = {
|
var config = {
|
||||||
open: '{{',
|
open: '{{', // 标签符前缀
|
||||||
close: '}}'
|
close: '}}' // 标签符后缀
|
||||||
};
|
};
|
||||||
|
|
||||||
var tool = {
|
// 模板工具
|
||||||
exp: function(str){
|
var tool = {
|
||||||
return new RegExp(str, 'g');
|
|
||||||
},
|
|
||||||
//匹配满足规则内容
|
|
||||||
query: function(type, _, __){
|
|
||||||
var types = [
|
|
||||||
'#([\\s\\S])+?', //js语句
|
|
||||||
'([^{#}])*?' //普通字段
|
|
||||||
][type || 0];
|
|
||||||
return exp((_||'') + config.open + types + config.close + (__||''));
|
|
||||||
},
|
|
||||||
escape: function(html){
|
escape: function(html){
|
||||||
var exp = /[<"'>]|&(?=#[a-zA-Z0-9]+)/g;
|
var exp = /[<"'>]|&(?=#[a-zA-Z0-9]+)/g;
|
||||||
if(html === undefined || html === null) return '';
|
if(html === undefined || html === null) return '';
|
||||||
|
@ -32,54 +23,89 @@ layui.define(function(exports){
|
||||||
return html.replace(/&(?!#?[a-zA-Z0-9]+;)/g, '&')
|
return html.replace(/&(?!#?[a-zA-Z0-9]+;)/g, '&')
|
||||||
.replace(/</g, '<').replace(/>/g, '>')
|
.replace(/</g, '<').replace(/>/g, '>')
|
||||||
.replace(/'/g, ''').replace(/"/g, '"');
|
.replace(/'/g, ''').replace(/"/g, '"');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 内部方法
|
||||||
|
var inner = {
|
||||||
|
exp: function(str){
|
||||||
|
return new RegExp(str, 'g');
|
||||||
},
|
},
|
||||||
error: function(e, tplog){
|
// 错误提示
|
||||||
|
error: function(e, source){
|
||||||
var error = 'Laytpl Error: ';
|
var error = 'Laytpl Error: ';
|
||||||
typeof console === 'object' && console.error(error + e + '\n'+ (tplog || ''));
|
typeof console === 'object' && console.error(error + e + '\n'+ (source || ''));
|
||||||
return error + e;
|
return error + e;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var exp = tool.exp, Tpl = function(tpl){
|
// constructor
|
||||||
this.tpl = tpl;
|
var Class = function(template, options){
|
||||||
|
var that = this;
|
||||||
|
that.config = that.config || {};
|
||||||
|
that.template = template;
|
||||||
|
|
||||||
|
// 简单属性合并
|
||||||
|
var extend = function(obj){
|
||||||
|
for(var i in obj){
|
||||||
|
that.config[i] = obj[i];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
extend(config);
|
||||||
|
extend(options);
|
||||||
};
|
};
|
||||||
|
|
||||||
Tpl.pt = Tpl.prototype;
|
// 标签正则
|
||||||
|
Class.prototype.tagExp = function(type, _, __){
|
||||||
|
var options = this.config;
|
||||||
|
var types = [
|
||||||
|
'#([\\s\\S])+?', // js 语句
|
||||||
|
'([^{#}])*?' // 普通字段
|
||||||
|
][type || 0];
|
||||||
|
|
||||||
window.errors = 0;
|
return inner.exp((_||'') + options.open + types + options.close + (__||''));
|
||||||
|
};
|
||||||
|
|
||||||
//编译模版
|
// 模版解析
|
||||||
Tpl.pt.parse = function(tpl, data){
|
Class.prototype.parse = function(template, data){
|
||||||
var that = this, tplog = tpl;
|
var that = this;
|
||||||
var jss = exp('^'+config.open+'#', ''), jsse = exp(config.close+'$', '');
|
var options = that.config;
|
||||||
|
var source = template;
|
||||||
|
var jss = inner.exp('^'+ options.open +'#', '');
|
||||||
|
var jsse = inner.exp(options.close +'$', '');
|
||||||
|
|
||||||
|
// 模板必须为 string 类型
|
||||||
|
if(typeof template !== 'string') return template;
|
||||||
|
|
||||||
tpl = tpl.replace(/\s+|\r|\t|\n/g, ' ')
|
// 正则解析
|
||||||
.replace(exp(config.open+'#'), config.open+'# ')
|
template = template.replace(/\s+|\r|\t|\n/g, ' ')
|
||||||
.replace(exp(config.close+'}'), '} '+config.close).replace(/\\/g, '\\\\')
|
.replace(inner.exp(options.open +'#'), options.open +'# ')
|
||||||
|
.replace(inner.exp(options.close +'}'), '} '+ options.close).replace(/\\/g, '\\\\')
|
||||||
|
|
||||||
//不匹配指定区域的内容
|
// 不匹配指定区域的内容
|
||||||
.replace(exp(config.open + '!(.+?)!' + config.close), function(str){
|
.replace(inner.exp(options.open + '!(.+?)!' + options.close), function(str){
|
||||||
str = str.replace(exp('^'+ config.open + '!'), '')
|
str = str.replace(inner.exp('^'+ options.open + '!'), '')
|
||||||
.replace(exp('!'+ config.close), '')
|
.replace(inner.exp('!'+ options.close), '')
|
||||||
.replace(exp(config.open + '|' + config.close), function(tag){
|
.replace(inner.exp(options.open + '|' + options.close), function(tag){
|
||||||
return tag.replace(/(.)/g, '\\$1')
|
return tag.replace(/(.)/g, '\\$1')
|
||||||
});
|
});
|
||||||
return str
|
return str
|
||||||
})
|
})
|
||||||
|
|
||||||
//匹配 JS 语法
|
// 匹配 JS 语法
|
||||||
.replace(/(?="|')/g, '\\').replace(tool.query(), function(str){
|
.replace(/(?="|')/g, '\\').replace(that.tagExp(), function(str){
|
||||||
str = str.replace(jss, '').replace(jsse, '');
|
str = str.replace(jss, '').replace(jsse, '');
|
||||||
return '";' + str.replace(/\\(.)/g, '$1') + ';view+="';
|
return '";' + str.replace(/\\(.)/g, '$1') + ';view+="';
|
||||||
})
|
})
|
||||||
|
|
||||||
//匹配普通输出语句
|
// 匹配普通输出语句
|
||||||
.replace(tool.query(1), function(str){
|
.replace(that.tagExp(1), function(str){
|
||||||
var start = '"+laytpl.escape(';
|
var start = '"+laytpl.escape(';
|
||||||
if(str.replace(/\s/g, '') === config.open+config.close){
|
if(str.replace(/\s/g, '') === options.open + options.close){
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
str = str.replace(exp(config.open+'|'+config.close), '');
|
str = str.replace(inner.exp(options.open + '|' + options.close), '');
|
||||||
if(/^=/.test(str)){
|
if(/^=/.test(str)){
|
||||||
str = str.replace(/^=/, '');
|
str = str.replace(/^=/, '');
|
||||||
} else if(/^-/.test(str)){
|
} else if(/^-/.test(str)){
|
||||||
|
@ -89,30 +115,35 @@ layui.define(function(exports){
|
||||||
return start + str.replace(/\\(.)/g, '$1') + ')+"';
|
return start + str.replace(/\\(.)/g, '$1') + ')+"';
|
||||||
});
|
});
|
||||||
|
|
||||||
tpl = '"use strict";var view = "' + tpl + '";return view;';
|
template = '"use strict";var view = "' + template + '";return view;';
|
||||||
|
|
||||||
try{
|
try {
|
||||||
that.cache = tpl = new Function('d, laytpl', tpl);
|
that.cache = template = new Function('d, laytpl', template);
|
||||||
return tpl(data, tool);
|
return template(data, tool);
|
||||||
} catch(e){
|
} catch(e) {
|
||||||
delete that.cache;
|
delete that.cache;
|
||||||
return tool.error(e, tplog);
|
return inner.error(e, source);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Tpl.pt.render = function(data, callback){
|
// 数据渲染
|
||||||
var that = this, tpl;
|
Class.prototype.render = function(data, callback){
|
||||||
if(!data) return tool.error('no data');
|
data = data || {};
|
||||||
tpl = that.cache ? that.cache(data, tool) : that.parse(that.tpl, data);
|
|
||||||
if(!callback) return tpl;
|
var that = this;
|
||||||
callback(tpl);
|
var result = that.cache ? that.cache(data, tool) : that.parse(that.template, data);
|
||||||
|
|
||||||
|
// 返回渲染结果
|
||||||
|
typeof callback === 'function' && callback(result);
|
||||||
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
var laytpl = function(tpl){
|
// 创建实例
|
||||||
if(typeof tpl !== 'string') return tool.error('Template not found');
|
var laytpl = function(template, options){
|
||||||
return new Tpl(tpl);
|
return new Class(template, options);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 配置全局属性
|
||||||
laytpl.config = function(options){
|
laytpl.config = function(options){
|
||||||
options = options || {};
|
options = options || {};
|
||||||
for(var i in options){
|
for(var i in options){
|
||||||
|
@ -120,8 +151,8 @@ layui.define(function(exports){
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
laytpl.v = '1.2.0';
|
laytpl.v = '2.0.0';
|
||||||
|
|
||||||
|
// export
|
||||||
exports('laytpl', laytpl);
|
exports('laytpl', laytpl);
|
||||||
|
|
||||||
});
|
});
|
Loading…
Reference in New Issue