作家
登录

浅析Prototype的模板类 Template

作者: 来源:www.28hudong.com 2013-03-30 00:37:41 阅读 我要评论

用过Prototype的人都知道,里面有个类叫做Template,用法示例如下: 复制代码 代码如下: var str = '#{what} may have gone, but there is a time of #{how}'; var object = { what : 'Swallows', how : 'return' } var template_1 = new Template(str); var result = template_1.evaluate(object); console.log('result:',result); //输出:'Swallows may have gone, but there is a time of return' 这么挺方便的,所以下面就简单的分析一下实现原理,也算是源码解读的一个笔记。 我们先看一下一般需求里面会用到的一些情况,还是用上面的例子,先决定我们的形式,替换的部分是形如#{what}的内容,其中what是一个object对象的一个关键字。 现在有个问题就是,如果object是一个嵌套的对象,我们该怎么替换? 即: 复制代码 代码如下: <script type="text/javascript"> var object = { what : { name : 'Swallows' }, how : 'return' } </script> 最开始的#{what}肯定不能满足要求,所以我们硬性规定,如果要实现嵌套对象的替换,写作#{what.name}或者#{what[name]}。 所以最开始的例子可以写作: 复制代码 代码如下: <script type="text/javascript"> var str = '#{what.name} may have gone, but there is a time of #{how}'; //或者str = '#{what[name]} may have gone, but there is a time of #{how}'; var object = { what : { name : 'Swallows' }, how : 'return' } var template_1 = new Template(str); var result = template_1.evaluate(object); console.log('result:',result); //输出:'Swallows may have gone, but there is a time of return' </script> 源码里面有个正则var pattern = /^([^.[]+|[((?:.*?[^\])?)])(.|[|$)/;就是用来实现这个目的的。依次类推,任何深层次的嵌套都可以实现。 要做替换,我们最核心的就是要有一个替换字符的方法,源码里面用的是gsub,下面给出一个gsub的最简版本: 复制代码 代码如下: <script type="text/javascript"> function gsub(str,pattern, replacement){ var result = '', source = str, match; //下面的每一次匹配都是分成三段来操作的 //相当于 $` $& $' while(source.length > 0){ match = source.match(pattern); if(match){ result += source.slice(0, match.index); result += replacement(match); source = source.slice(match.index + match[0].length); }else{ result += source; source = ''; } } return result; } </script> 这个调用方法和原理跟我前面涉及的replace类似,基本可以互换。http://www.cnblogs.com/xesam/archive/2011/12/05/2276783.html 复制代码 代码如下: <script type="text/javascript"> console.log(gsub('there is a time of #{how}',/(^|.|r|n)(#{(.*?)})/,function{ return 'demo'; })) //输出there is a time ofdemo </script> 下面回到Template来,基本要求:有类有方法 复制代码 代码如下: <script type="text/javascript"> var Template = function(template, pattern){ this.template = template.toString(); this.pattern = pattern || Template.Pattern; }; Template.Pattern = /(^|.|r|n)(#{(.*?)})/; Template.prototype.evaluate = function(object){} </script> template就是最初例子中的str,pattern是匹配规则,object就是最初例子中的object;现在重点剩下evaluate方法的实现: 直接调用gsub方法,主要是gsub中replacement的方法了。 可能出现的情况, 第一、object是一个空对象,那么我们直接删除需要替换的部分 比如 var str = '#{what} may have gone, but there is a time of #{how}'; var object = {} 那么就直接返回' may have gone, but there is a time of ' 第二、转义部分直接保留 复制代码 代码如下: var str = '\#{what} may have gone, but there is a time of \#{how}'; var object = { what : 'Swallows', how : 'return' } 那么就直接返回'\#{what} may have gone, but there is a time of \#{how}'; 这些情况在代码中都要处理,具体代码如下 复制代码 代码如下: Template.prototype.evaluate = function(object){ //gsub(str,pattern, replacement) return gsub(this.template,this.pattern,function(match){ var before = match[1];//这里的match[1]就是Template.Pattern中(^|.|r|n)匹配的部分 var content = match[2];//这里的match[1]就是Template.Pattern中(#{(.*?)})匹配的部分 var expr = match[3];//这里的match[1]就是Template.Pattern中(.*?)匹配的部分 //示例: //对于 s#{what} 来说before='s',content='#{what}',expr='what' //第一、object是一个空对象,那么我们直接删除需要替换的部分 if(object == null){ return (match[1] + ''); } //第二、转义部分直接保留 if (before == '\'){ return content; } //除了上面的两种情况,下面是正常的替换流程。 var ctx = object; //下面这个正则我在前面说过,是为了匹配嵌套对象的。看最后面的(.|[|$)是为了确定有没有嵌套的子对象匹配。 //#{what.name}中的'.' //或者#{what[name]}中的'[' //也就是下面的match[3] var pattern = /^([^.[]+|[((?:.*?[^\])?)])(.|[|$)/; match = pattern.exec(expr); while (match != null) { if(/^[/.test(match[1])){ var comp = match[2].replace(/\\]/g, ']'); }else{ var comp = match[1]; } ctx = ctx[comp];//如果ctx[comp]是一个字符串,那么下面一步就可以收工了,如果ctx[comp]还是一个对象,那么抱歉,加班继续干吧。 if (null == ctx || '' == match[3]){//需要替换的不是object的嵌套子对象,那么就直接中断循环。替换成功,下班。 break; } //下面的仅仅是为了剥离出来关键字,其他操作用在循环里面再来一次。 if('[' == match[3]){ expr = expr.substring(match[1].length) }else{ expr = expr.substring(match[0].length) } match = pattern.exec(expr); } return before + ctx; }); }; 当然,源码中并没有这么简单,还参杂了一写检测和判断,比如替换str的非法字符,处理replacement为字符串的情况等等。具体可以去查看源码。 可能有些复杂的就是处理replacement为字符串的情况,gsub和Template有一个嵌套调用的情况,不过意思都一样,最后丢回一个函数就可以了。

  推荐阅读

  js 可拖动列表实现代码

补充一点: 要禁止移动中选中文字,FF可以设置CSS xxxx{-moz-user-select:none;} 其他的浏览器可以设置 XXXX.onselectstart = function(){return false} 一种实现原理就是点击没目标元素之后,创建一个占位元素(或>>>详细阅读


本文标题:浅析Prototype的模板类 Template

地址:http://www.17bianji.com/kaifa2/JS/23846.html

关键词: 探索发现

乐购科技部分新闻及文章转载自互联网,供读者交流和学习,若有涉及作者版权等问题请及时与我们联系,以便更正、删除或按规定办理。感谢所有提供资讯的网站,欢迎各类媒体与乐购科技进行文章共享合作。

网友点评
自媒体专栏

评论

热度

精彩导读
栏目ID=71的表不存在(操作类型=0)