Heim  >  Artikel  >  Web-Frontend  >  仿服务器端脚本方式的JS模板实现方法_javascript技巧

仿服务器端脚本方式的JS模板实现方法_javascript技巧

WBOY
WBOYOriginal
2016-05-16 19:14:10978Durchsuche

http://bbs.51js.com/thread-65160-1-1.html



jssp演示
<script> <BR>/** <BR>* @description: <BR>* 使用javascript模仿JSP的页面解析和运行,运行于客户端 <BR>* 允许应用人员象开发JSP页面一样使用<%..%> <BR>* 允许页面动态包括子页面(同步读取页面) <BR>* <BR>**/ <br><br>//@--------------------------------------------------------------------- JSSP声明 <BR>var jssp=function(){}; <br><br>/** <BR> * 页面缓存管理实例对象 <BR> */ <BR>jssp.cacheInstance=null; <BR>/** <BR> * 页面加载实例对象 <BR> */ <BR>jssp.pageLoaderInstance=null; <br><br>/** <BR> * 在指定dom插入pagePath的执行后的页面内容 <BR> */ <BR>jssp.render=function(pagePath,dom){ <BR> if(typeof dom=="string") dom=document.getElementById(dom); <BR> var content=jssp.Core.run(pagePath); <BR> dom.innerHTML=content; <BR>} <br><br>//@------------------------------------------------------------------------ JSSP运行配置 <BR>/** <BR> * 引擎运行全局配置 <BR> */ <BR>jssp.Config={}; <BR>/** <BR> * 如果在客户端运行,是否缓存解析的页面 <BR> */ <BR>jssp.Config.cachable=true; <BR>/** <BR> * 当jssp.Config.cacheable为true且在 <BR> */ <BR>jssp.Config.cacheClass="jssp.Cache.DefaultCache"; <BR>/** <BR> * 页面内容读取器 <BR> */ <BR>jssp.Config.pageLoaderClass="jssp.Core.PageLoader.Ajax"; <br><br>//@------------------------------------------------------------------------ JSSP页面缓存类 <BR>/** <BR> * 页面缓存类 <BR> */ <BR>jssp.Cache=function(){} <BR>/** <BR> * 设置缓存 <BR> */ <BR>jssp.Cache.prototype.set=function(key,cache){} <BR>/** <BR> * 得到缓存 <BR> */ <BR>jssp.Cache.prototype.get=function(key){} <BR>/** <BR> * 默认的缓存实现类 <BR> */ <BR>jssp.Cache.DefaultCache=function(){ <BR> this.caches={}; <BR>} <BR>jssp.Cache.DefaultCache.prototype.set=function(key,cache){ <BR> this.caches[key]=cache; <BR>} <BR>jssp.Cache.DefaultCache.prototype.get=function(key){ <BR> return this.caches[key]; <BR>} <br><br>//@----------------------------------------------------------------------- JSSP运行上下文类 <BR>/** <BR> * jssp页面的执行上下文对象 <BR> * @member params 请求参数数组 <BR> * @member cookies 操作cookies对象 jssp.Cookies <BR> * @member out 页面流输出对象 jssp.Out <BR> * @method setAttribute 设置上下文参数 <BR> * @method getAttribute 得到上下文参数 <BR> * @method removeAttribute 删除上下文参数 <BR> * @method include 动态包含子页面 <BR> * @method getCookies,getParameter,getParameters,getOut <BR> * @param pageUrl 运行的上下文参数 <BR> * @param context 父页面的上下文对象 <BR> */ <BR> jssp.Context=function(pageUrl,context){ <BR> this.params=this._resolveParam(pageUrl); <BR> if(!context){ <BR> this.cookies=jssp.Cookies; <BR> this.out=new jssp.Out(); <BR> this.attributes=[]; <BR> }else{ <BR> this.context=context; <BR> this.isIncluded=true; <BR> } <br><br> } <BR> /** <BR> * 解析页面后缀参数 <BR> */ <BR> jssp.Context.prototype._resolveParam=function(pageUrl){ <BR> var i1=pageUrl.indexOf("?"); <BR> if(i1<=0) return []; <BR> pageUrl=pageUrl.substring(i1+1); <BR> var s1=pageUrl.split("&"); <BR> var params=[]; <BR> for(var i=0;i<s1.length;i++){ <BR> var s2=s1[i].split("="); <BR> var key=s2[0];var value=s2[1]; <BR> var ps=params[key]; <BR> if(!ps) ps=[]; <BR> ps[ps.length]=value; <BR> params[key]=ps; <BR> } <BR> return params; <BR> } <BR> /** <BR> * 设置参数值 <BR> */ <BR> jssp.Context.prototype.setAttribute=function(key,value){ <BR> if(!this.context) <BR> this.attributes[key]=value; <BR> else <BR> this.context.setAttribute(key,value); <BR> } <BR> /** <BR> * 得到参数值 <BR> */ <BR> jssp.Context.prototype.getAttribute=function(key){ <BR> if(!this.context) <BR> return this.attributes[key]; <BR> else <BR> return this.context.getAttribute(key); <BR> } <BR> /** <BR> * 删除指定键的参数值 <BR> */ <BR> jssp.Context.prototype.removeAttribute=function(key){ <BR> if(!this.context) <BR> this.attributes[key]=undefined; <BR> else <BR> this.context.removeAttribute(key); <BR> } <BR> /** <BR> * 得到请求参数值 <BR> */ <BR> jssp.Context.prototype.getParameter=function(key){ <BR> var ps=this.params[key]; <BR> if(!ps) return this.context?this.context.getParameter(key):undefined; <BR> return ps.join(","); <BR> } <BR> /** <BR> * 得到有重复参数的值 <BR> */ <BR> jssp.Context.prototype.getParameters=function(key){ <BR> var pss=this.params[key]; <BR> if(!pss) pss=this.context?this.context.getParameters(key):undefined; <BR> return pss; <BR> } <BR> /** <BR> * 得到cookies对象 <BR> */ <BR> jssp.Context.prototype.getCookies=function(){ <BR> if(!this.context) <BR> return this.cookies; <BR> else <BR> return this.context.getCookies(); <BR> } <BR> /** <BR> * 得到输出流OUT对象 <BR> */ <BR> jssp.Context.prototype.getOut=function(){ <BR> if(!this.context) <BR> return this.out; <BR> else <BR> return this.context.getOut(); <BR> } <BR> /** <BR> * 动态包含子页面 <BR> */ <BR> jssp.Context.prototype.include=function(childPageUrl){ <BR> this.getOut().print(jssp.Core.run(childPageUrl,this)); <BR> } <br><br> jssp.Context.prototype.isIncluded=false;//判断当前页面是否被包含的 <br><br>//@-----------------------------------------------------------------------JSSP运行cookies操作类 <BR>/** <BR> * 简单操纵cookies方法 <BR> */ <BR>jssp.Cookies=function(){} <BR>/** <BR> * 设置cookie项 <BR> */ <BR>jssp.Cookies.set=function(key,value){ <BR> document.cookie=key+"="+escape(value)+";"; <BR>} <BR>/** <BR> * 得到cookie项 <BR> */ <BR>jssp.Cookies.get=function(key){ <BR> var aCookie=document.cookie.split("; "); <BR> for(var i=0;i<aCookie.length;i++){ <BR> var aCrumb=aCookie[i].split("="); <BR> if(key==aCrumb[0]) <BR> return unescape(aCrumb[1]); <BR> } <BR>} <BR>/** <BR> * 删除cookies项 <BR> */ <BR>jssp.Cookies.remove=function(key){ <BR> document.cookie=key+"=null; expires=Fri, 31 Dec 1999 23:59:59 GMT;"; <BR>} <BR>//@------------------------------------------------------------------------ JSSP页面运行输出流类 <BR>/** <BR> * 页面流输出对象 <BR> */ <BR>jssp.Out=function(){ <BR> this.datas=[];//数据流片断 <BR> this._index=0; <BR>} <BR>/** <BR> * 把页面流片断放入缓冲区 <BR> */ <BR>jssp.Out.prototype.print=function(s){ <BR> this.datas[this._index++]=s; <BR>} <BR>/** <BR> * 输出缓冲区里的数据 <BR> */ <BR>jssp.Out.prototype.flush=function(){ <BR> var data=this.datas.join(""); <BR> this.datas=[];this._index=0; <BR> return data; <BR>} <BR>//@--------------------------------------------------------------------------JSSP页面核心类声明 <BR>jssp.Core=function(){} <BR>//@--------------------------------------------------------------------------JSSP页面解析实现类 <BR>/** <BR> * 页面解析 <BR> * @param pageContent JSSP页面内容 <BR> */ <BR>jssp.Core.parse=function(pageContent){ <br><br> var strBuffer=[];//解析后文本存放的缓冲区 <BR> var point=0;//缓冲区指针 <BR> var lineNumber=1;//解析的当前行 <br><br> try{ <BR> var betweenPerc=false; <BR> var isPrint=false; <BR> strBuffer[point++]="function($context){\n"; <BR> strBuffer[point++]="var $out=$context.getOut();\n"; <BR> strBuffer[point++]="var $cookies=$context.getCookies();\n"; <BR> strBuffer[point++]="try{\n"; <BR> strBuffer[point++]="$out.print(unescape('"; <BR> var line=""; <BR> var value=pageContent; <BR> var len=value.length; <BR> for(var i=0;i<len;i++){ <BR> var nextTwo=""; <BR> if(i<=len-2) nextTwo=value.charAt(i)+value.charAt(i+1); <BR> var nextThree=""; <BR> if(i<=len-3) nextThree=nextTwo+value.charAt(i+2); <BR> if(nextTwo=="<%"&&nextThree!="<%="&&nextThree!="<%@"){ <BR> strBuffer[point++]="'));\n"; <BR> betweenPerc=true; <BR> i+=1; <BR> }else if(nextTwo=="<%"&&nextThree=="<%="&&nextThree!="<%@"){ <BR> strBuffer[point++]=escape(line)+"'));\n"; <BR> line=""; <BR> strBuffer[point++]=" $out.print( "; <BR> betweenPerc=true; <BR> isPrint=true; <BR> i+=2; <BR> }else if(nextTwo=="<%"&&nextThree!="<%="&&nextThree=="<%@"){ <BR> i+=3; <BR> var directive=""; <BR> while(nextTwo!="%>"){ <BR> directive+=value.charAt(i); <BR> i++; <BR> if(i<=value.length-2){ <BR> nextTwo=value.charAt(i)+value.charAt(i+1); <BR> } <BR> } <BR> strBuffer[point++]=escape(line)+"'));\n"; <BR> line=""; <BR> strBuffer[point++]=jssp.Core.parse._handleDirective(directive); <BR> strBuffer[point++]=" $out.print(unescape('"; <BR> i++; <BR> }else if(nextTwo=="%>"){ <BR> strBuffer[point++]=(isPrint?");":"")+"\n $out.print(unescape('"; <BR> if(!betweenPerc) throw new jssp.Core.parse.ParseException("解析错误","必须用'%>'作为结束标签"); <BR> betweenPerc=false; <BR> isPrint=false; <BR> i+=1; <BR> }else if(value.charAt(i)==String.fromCharCode(10)){ <BR> if(!betweenPerc){ <BR> strBuffer[point++]=escape(line)+"\\n'));\n"+" $out.print(unescape('"; <BR> line=""; <BR> lineNumber++; <BR> } <BR> }else if(value.charAt(i)==String.fromCharCode(13)){ <BR> if(betweenPerc) strBuffer[point++]="\n"; <BR> }else{ <BR> if(betweenPerc) <BR> strBuffer[point++]=value.charAt(i); <BR> else <BR> line+=value.charAt(i); <BR> } <BR> } <BR> strBuffer[point++]=escape(line)+"'));\n"; <BR> strBuffer[point++]="}catch(e){\n"; <BR> strBuffer[point++]="return '"+"执行页面发生异常.异常类型:'+e.name+'. 错误消息: '+e.message;\n"; <BR> strBuffer[point++]="}\n"; <BR> strBuffer[point++]="if(!$context.isIncluded) return $out.flush();\n"; <BR> strBuffer[point++]="}\n"; <BR> }catch(e){ <BR> point=0; <BR> strBuffer=[]; <BR> strBuffer[point++]="function($context){\n"; <BR> strBuffer[point++]="return \""+"An exception occurred while parsing on line "+lineNumber+". Error type: "+e.name+". Error message: "+e.message+"\";"; <BR> strBuffer[point++]="}"; <BR> } <BR> var out=strBuffer.join(""); <BR> return out; <BR>} <BR>/** <BR> * 解析指示头 <BR> */ <BR>jssp.Core.parse._handleDirective=function(directive){ <br><br> var i = 0; <br><br> var tolkenIndex = 0; <BR> var tolken = new Array(); <br><br> //Skip first spaces; <BR> while ( directive.charAt(i) == ' ' ) { <BR> i++; <BR> } <br><br> tolken[tolkenIndex] = ""; <BR> while ( directive.charAt(i) != ' ' && i <= directive.length ) { <BR> tolken[tolkenIndex] += directive.charAt(i); <BR> i++; <BR> } <br><br> tolkenIndex++; <br><br> //Skip first spaces; <BR> while ( directive.charAt(i) == ' ' ) { <BR> i++; <BR> } <br><br> tolken[tolkenIndex] = ""; <BR> while ( directive.charAt(i) != ' ' && directive.charAt(i) != '=' && i <= directive.length ) { <BR> tolken[tolkenIndex] += directive.charAt(i); <BR> i++; <BR> } <br><br> tolkenIndex++; <br><br> //Skip first spaces; <BR> while ( directive.charAt(i) == ' ' ) { <BR> i++; <BR> } <br><br> if( directive.charAt(i) != '=' ) <BR> throw new jssp.Core.parse.ParseException("Sintax error", "Tolken = expected attribute"); <BR> i++ <br><br> //Skip first spaces; <BR> while ( directive.charAt(i) == ' ' ) { <BR> i++; <BR> } <br><br> tolken[tolkenIndex] = ""; <BR> while ( directive.charAt(i) != ' ' && i <= directive.length ) { <BR> tolken[tolkenIndex] += directive.charAt(i); <BR> i++; <BR> } <BR> tolkenIndex++; <br><br> //Skip first spaces; <BR> while ( directive.charAt(i) == ' ' && i <= directive.length ) { <BR> i++; <BR> } <br><br> tolken[tolkenIndex] = ""; <BR> while ( directive.charAt(i) != ' ' && directive.charAt(i) != '=' && i <= directive.length && i <= directive.length ) { <BR> tolken[tolkenIndex] += directive.charAt(i); <BR> i++; <BR> } <br><br> tolkenIndex++; <br><br> if( directive.charAt(i) != '=' && i <= directive.length ) <BR> throw new jssp.Core.parse.ParseException("Sintax error", "Tolken = expected after attribute" ); <BR> i++ <br><br> tolken[tolkenIndex] = ""; <BR> while ( directive.charAt(i) != ' ' && i <= directive.length && i <= directive.length ) { <BR> tolken[tolkenIndex] += directive.charAt(i); <BR> i++; <BR> } <br><br> var file = ""; <BR> var context = ""; <br><br> if ( tolken[0] != "include" ) <BR> throw new jssp.Core.parse.ParseException("Sintax error","Directive " + tolken[0] + " unknown.") ; <br><br> if ( tolken[1] != "file" ) <BR> throw new jssp.Core.parse.ParseException("Sintax error", "Attribute file expected after include." ); <BR> else file = tolken[2]; <br><br> if ( tolken[3] != "context" && tolken[3] != "" ) <BR> throw new jssp.Core.parse.ParseException( "Sintax error", "Attribute context expected after file."); <BR> else if ( tolken[3] == "context" ) <BR> context = tolken[4] <BR> else <BR> context = "$context"; <br><br> var out = "$context.include(" + file + ");\n"; <br><br> return out; <BR>} <br><br>/** <BR> * 解析异常 <BR> */ <BR>jssp.Core.parse.ParseException=function(name,message) { <BR> this.name=name; <BR> this.message=message; <BR>} <BR>//@--------------------------------------------------------------------------------页面内容加载接口定义 <BR>/** <BR> * 页面内容加载类接口定义 <BR> */ <BR>jssp.Core.PageLoader=function(){} <BR>/** <BR> * 读取页面文本 <BR> */ <BR>jssp.Core.PageLoader.prototype.loadPage=function(pagePath){throw "不能直接调用接口或您还未实现此方法!";} <BR>//@--------------------------------------------------------------------------------页面运行实现方法 <BR>/** <BR> * @param pagePath 加载页面 <BR> * @parma context 上下文对象 <BR> */ <BR>jssp.Core.run=function(pagePath,context){ <br><br> if(!jssp.pageLoaderInstance){ <BR> //jssp引擎初始化 <BR> if(jssp.Config.cachable) jssp.cacheInstance=eval("new "+jssp.Config.cacheClass+"();"); <BR> jssp.pageLoaderInstance=eval("new "+jssp.Config.pageLoaderClass+"();"); <BR> } <br><br> var key=pagePath;if(key.indexOf("?")>0) key=key.substring(0,key.indexOf("?")); <br><br> var processer=jssp.Config.cachable?jssp.cacheInstance.get(key):null; <BR> if(!processer){ <BR> eval("processer="+jssp.Core.parse(jssp.pageLoaderInstance.loadPage(pagePath))); <BR> if(jssp.Config.cachable) jssp.cacheInstance.set(key,processer); <BR> }else{ <BR> //alert("cache") <BR> } <br><br> if(!context) <BR> context=new jssp.Context(pagePath); <BR> else <BR> context=new jssp.Context(pagePath,context); <BR> return processer(context); <BR>} <BR>//@-----------------------------------------------------------------------------------AJAX加载页面实现 <BR>jssp.Core.PageLoader.Ajax=function(){} <br><br>jssp.Core.PageLoader.Ajax.prototype.loadPage=function(pagePath){ <BR> var content=jssp.Ajax.send(pagePath,"GET",false); <BR> if(!content) { <BR> alert("请求页面:"+pagePath+" 返回为null!");return null; <BR> } <BR> return content; <BR>} <BR>//@-----------------------------------------------------------------------------------AJAX操作实现 <BR>jssp.Ajax=function(){} <BR>/** <BR> * 建立HTTP连接 <BR> */ <BR>jssp.Ajax.createHttpRequest=function(){ <BR> if(window.XMLHttpRequest) <BR> return new XMLHttpRequest(); <BR> var request=null; <BR> try{ <BR> request=new ActiveXObject("Msxml2.XMLHTTP.4.0"); <BR> }catch(e){ <BR> try{ <BR> request=new ActiveXObject("Msxml2.XMLHTTP"); <BR> }catch(e){ <BR> try{ <BR> request=new ActiveXObject("microsoft.XMLHTTP"); <BR> }catch(e){ <BR> throw "XMLHTTPRequest组件客户端不支持!"; <BR> } <BR> } <BR> } <BR> return request; <BR>} <br><br>/** <BR> * 发送AJAX请求 <BR> * @param url 请求页面 <BR> * @param method 请求方法 get or post <BR> * @param async 是否为异步调用 <BR> * @param callback 回调函数 <BR> * @param preHook 调用前执行函数 <BR> * @param postHook 调用后请求返回执行函数 <BR> */ <BR>jssp.Ajax.send=function(url,method,async,callback,preHook,postHook){ <BR> method=method.toUpperCase(); <br><br> if(typeof preHook=="function") preHook(); <br><br> var request=jssp.Ajax.createHttpRequest(); <BR> request.open(method,url,async); <BR> if(async){ <BR> if(typeof callback!="function") throw "必须要设置回调函数"; <BR> request.onreadystatechange=function(){ <BR> jssp.Ajax.callback(request,callback,postHook); <BR> }; <BR> } <BR> request.send(null); <BR> if(!async) { <BR> if(request.status==200||request.status==304) <BR> return jssp.Ajax._chartset(request); <BR> else <BR> return null; <BR> } <BR>} <BR>/** <BR> * 接受响应,调用自定义回调函数 <BR> */ <BR>jssp.Ajax.callback=function(response,callback,postHook){ <BR> if(response.readyState!=4) return; <BR> var text; <BR> if(response.status==200||response.status==304){ <BR> text=jssp.Ajax._chartset(response); <BR> } <BR> callback(text); <BR> if(typeof postHook=="function") postHook(); <BR>} <BR>/** <BR> * 中文乱码处理 <BR> */ <BR>jssp.Ajax._chartset=function(r){ <BR> var t=bytes2BSTR(r.responseBody); <BR> return t; <BR>} <br><br></script>

<script> <BR> jssp.Config.pageLoaderClass="jssp.Core.PageLoader.CustomerInput";//设置页面读取接口 <BR> jssp.Config.cachable=false; <BR> jssp.Core.PageLoader.CustomerInput=function(){} <BR> jssp.Core.PageLoader.CustomerInput.prototype.loadPage=function(pagePath){ <BR> if(pagePath.substring(0,10)!="hello.jssp") return "测试包含子页面,路径:"+pagePath; <BR> return document.getElementById("pageContent").value; <BR> } <BR> function showPage(){ <BR> jssp.render("hello.jssp?name="+Math.random(),"pageArea"); <BR> } <BR></script>




输入JSSP脚本内容:








 
Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn