>웹 프론트엔드 >JS 튜토리얼 >서버사이드 스크립팅_javascript 기술을 모방한 JS 템플릿 구현 방법

서버사이드 스크립팅_javascript 기술을 모방한 JS 템플릿 구현 방법

WBOY
WBOY원래의
2016-05-16 19:14:101055검색

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脚本内容:








 
성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.