JScript 快速开发框架 Edk:模板

简介: 网页模板是把动态的数据和静态的表现组装到一起的工具,使得内容与表现方式可以分离,是 Web 开发中的重要技术手段。早期的 Web 开发很简单,还没“模板 ”的概念。只需把数据提取出来,放在 HTML 里面显示就达到程序的目的。

网页模板是把动态的数据和静态的表现组装到一起的工具,使得内容与表现方式可以分离,是 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.toString
		isObject.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部分,即表示全部就是trueBlock
			replace.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);
	}

};
这是我第一次写的模板,纯练手,因此非常粗糙。


目录
相关文章
|
数据安全/隐私保护 网络架构
DSL线路如何工作?
【4月更文挑战第15天】
491 3
DSL线路如何工作?
|
9月前
|
机器学习/深度学习 分布式计算 数据挖掘
MaxFrame 性能评测:阿里云MaxCompute上的分布式Pandas引擎
MaxFrame是一款兼容Pandas API的分布式数据分析工具,基于MaxCompute平台,极大提升了大规模数据处理效率。其核心优势在于结合了Pandas的易用性和MaxCompute的分布式计算能力,无需学习新编程模型即可处理海量数据。性能测试显示,在涉及`groupby`和`merge`等复杂操作时,MaxFrame相比本地Pandas有显著性能提升,最高可达9倍。适用于大规模数据分析、数据清洗、预处理及机器学习特征工程等场景。尽管存在网络延迟和资源消耗等问题,MaxFrame仍是处理TB级甚至PB级数据的理想选择。
179 6
|
安全 Java 网络安全
Struts 2.0.0 至 2.1.8.1 远程命令执行(CVE-2010-1870)
Struts 2.0.0 至 2.1.8.1 远程命令执行(CVE-2010-1870)
|
10月前
|
机器学习/深度学习 存储 人工智能
人工智能的伦理困境与挑战
在本文中,我们将探讨人工智能技术的快速发展所带来的一系列伦理问题和挑战。随着AI技术的不断进步和应用范围的扩大,如何确保其发展符合道德标准、保护个人隐私以及避免潜在的社会不公成为了亟待解决的问题。本文旨在通过分析当前AI领域面临的主要伦理困境,并提出可能的解决方案或缓解措施,以促进更加负责任地使用和发展人工智能技术。
1005 1
|
人工智能 数据可视化 程序员
精心整理自学python的宝藏网站,不看亏死
精心整理自学python的宝藏网站,不看亏死
529 4
精心整理自学python的宝藏网站,不看亏死
|
SQL 存储 数据处理
实时计算 Flink版产品使用合集之flink-connector-mysql-cdc 和 flink-sql-connector-mysql-cdc有什么区别
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
659 1
|
机器学习/深度学习 存储 JSON
《零基础实践深度学习》2.3 手写数字识别之数据处理
这篇文章详细介绍了手写数字识别任务中数据处理的优化方法,包括数据读取、划分数据集、生成批次数据、训练样本乱序和校验数据有效性等环节,并通过代码示例展示了如何使用飞桨框架对MNIST数据集进行有效处理以提升模型训练效果。
|
安全 开发工具
微信小游戏制作工具中的键盘插件的使用
微信小游戏制作工具中的键盘插件的使用
873 0
|
存储 弹性计算 运维
阿里云无影云电脑怎么买?阿里无影云电脑仅19.9元/月起
阿里云无影云电脑怎么买?阿里无影云电脑仅19.9元/月起,阿里云无影云电脑配置具体价格表,无影云桌面4核8G企业办公型云电脑可以免费使用3个月,无影云电脑地域不同价格不同,无影云电脑价格是由云桌面配置、云盘价格、互联网访问带宽价格、AD Connector 价格、桌面组共用桌面session 价格等费用组成
2229 2
|
存储 缓存 运维
企业上云方案:阿里云企业六大通用场景为企业提供多场景、一站式上云服务
阿里云为企业提供企业上云、企业初创必备、数字营销、企业办公、企业安全、企业数据六大上云场景、一站式上云服务(解决方案),为企业提供多场景、一站式上云服务,满足企业各个发展阶段的软硬件需求,助力您的事业腾飞!
1030 1
企业上云方案:阿里云企业六大通用场景为企业提供多场景、一站式上云服务

热门文章

最新文章