JScript 快速开发框架 Edk:模板

来源:互联网 发布:卓智网络怎么样 编辑:程序博客网 时间:2024/06/08 13:40

网页模板是把动态的数据和静态的表现组装到一起的工具,使得内容与表现方式可以分离,是 Web 开发中的重要技术手段。早期的 Web 开发很简单,还没“模板 ”的概念。只需把数据提取出来,放在 HTML 里面显示就达到程序的目的。HTML代码混合于逻辑代码之中,HTML 就是直接显示的内容,内嵌在 HMTL 中<% ... %>表示为后台(服务端)执行代码,但很多情况<% ... %>中又有 HTML 的片段,至于怎么拼凑出 HTML 片段的方式方法各式各样、与多种的后台语言掺杂一起( ASP、PHP、JSP )各显神通。

$$.tpl = {fillData : function(tpl, data){// 匹配闭合tag的正则。var divBlock = '<{0}\\s*[^>]*>((?:(?=([^<]+))\\2|<(?!{0}\\s*[^>]*>))*?)<\/({0})>';var matchValue = (function(){var regexp    = /{([^}\n]*)}/ig,execJS   = /^\[([^\]]*)\]$/,getParent = /^parent\.\b(\w*)\b$/i,getRoot   = /^root\.\b(\w*)\b$/i;/** * @private * @param {mixed} v * @return {Boolean} 是否hash(是否对象)。 */function isObject(v){return !!v && isObject.toString.call(v) == isObject.token;}isObject.toString = Object.prototype.toStringisObject.token    = '[object Object]';/** * 替换置,如果未发现匹配的值,返回什么?一般原模版的格式({xxx}),即m1。 * 注意那些无意义的值除外。 */function falsey(value, tpl){switch(value){case false:return 'false';case '':return value;case 0:return value;}return !!value ? value : tpl;} function replace(m1, m2){var  jsCode,parent  = arguments.callee.parent ,root = arguments.callee.root;if(execJS.test(m2)){execJS.lastIndex = 0;jsCode = execJS.exec(m2);jsCode = jsCode[1];try{ // 写try之目的为容错性的设计。with(this){jsCode = eval(jsCode);}return jsCode;}catch(e){return '空值';}}if(isObject(parent) && getParent.test(m2)){ /* 父级寻址 */getParent.lastIndex = 0;m2 = m2.match(getParent);m2 = m2[1];return falsey(parent[m2], m1);}else if(isObject(root) && getRoot.test(m2)){ /* 全称寻址 */getRoot.lastIndex = 0;m2 = m2.match(getRoot);m2 = m2[1];return falsey(root[m2], m1);}else{return falsey(this[m2], m1);}} /**  * Lazy function  * @param {String} tpl  * @param {Object} dataObj  * @param {Object} parentObj  * @return {String}  */return function(tpl, dataObj, parentObj){if(!replace.root){replace.root = $$.tpl.root;}replace.parent = parentObj || 'itself'; // 无else部分,即表示全部就是trueBlockreplace.scope  = dataObj;return tpl.replace(regexp, replace.delegate());// set scope object!}})();var matchIf = (function(){var  elseReg = /<else\s*\/?>/i,evalReg = /<if\s*(?:eval="([\w\d=<>\.!'\|\(\)]*)")[^>]*>/i,tabReg  = /\t{2}/g,ifReg   = new RegExp(divBlock.format('if'), 'ig');/** * 运算<if eval="exp">内容。 * @param {Object} data * @param {Object} parent * @param {String} ifTag * @return {Boolean} */function evalExp(data, parent, ifTag){var exp;evalReg.lastIndex = 0;if(!evalReg.test(ifTag)){$$.console.error('输入的标签{0}不是一个标准的if tag'.format(ifTag));throw '不是一个标准的if tag';}evalReg.lastIndex = 0;exp = evalReg.exec(ifTag);exp = exp[1];exp = '(' + exp +')'; // make it as the Expression 表达式//debugger;// 通过with(data){}给定对象可见的范围。如果没有matchedObj,则为this。这也是有可能的。with(data || parent || this){try{exp = !!eval(exp);}catch(e){exp = false;}}return exp;}/** * @this {OBject} 值对象 */function replace(m1, m2){var  evalResult // 运算表达式后的结果,trueBlock// true块,falseBlock = null// false块,默认没有elseReg.lastIndex = 0;if(elseReg.test(m2)){// 有else部分var arr = m2.split(elseReg);if(!arr || arr.length < 2){$$.console.error('if-else不完整');throw "if-else不完整";}; trueBlock  = arr[0];falseBlock = arr[1];}else{trueBlock  = m2; // 无else部分,即表示全部就是trueBlock}trueBlock  = $$.trim(trueBlock);trueBlock  = trueBlock.replace(tabReg, '\t');// 消除多余tab符。// 求 if 的表达式evalResult = evalExp(this, arguments.callee.parent, m1);if(evalResult){return trueBlock;}else if(!evalResult && falseBlock == null){return '';}else if(!evalResult && falseBlock){return falseBlock;}else{// 不应该会走到这里的。若真的走到便抛出一个异常。$$.console.error('求if-else块时发生致命错误!');throw '求if-else块时发生致命错误!';}}return function(tpl, data, parentData){ifReg.lastIndex = 0;// 有global时需要注意 lastIndex的问题。if(ifReg.test(tpl)){replace.parent = parentData;replace.scope  = data;return tpl.replace(ifReg, replace.delegate());}else{return tpl;}}})();function replace(m1, m2, m3, m4){var      parentData = this,values= parentData[m4],callee= $$.tpl.fillData    ,str = '',arrTpl;        if(values && !values.pop){    return callee(m2, values);// 递归 for sub    }else if(values && values.pop){/* 有时候会因为大小写问题,无法匹配。请检查key即(m4)是否一致 */        m2 = callee(m2, values);// 递归 for sub        for(var i = 0, j = values.length; i < j; i++){value  = values[i];m2   = matchIf(m2, value, parentData); arrTpl = callee(m2, value);str += matchValue(arrTpl, value, parentData);} return str;    }else if(values == false /* 特定为false的情况 */ ){    return str;    }else{    $$.console.warn('No data provided');// 怎么数据源没提供数据? 宜debug之    return 'edkTpl_nothing';    }}/** * @param  {String} tpl * @param  {Object} data * @return {String} */$$.tpl.fillData = function (tpl, data){if(!$$.tpl.root){$$.tpl.root = data;}    if(data && !data.pop){    replace.scope = data;    var _replace = replace.delegate();        for(var i in data){tpl = tpl.replace(new RegExp(divBlock.format(i), 'i'), _replace);    }        tpl = matchIf(tpl, data, data);         return matchValue(tpl, data);    }else if(data && data.pop){    return tpl;    }else if(!data){//    throw '没有输入数据的参数 data?';    }    return '';}return $$.tpl.fillData(tpl, data);}};
这是我第一次写的模板,纯练手,因此非常粗糙。