最新文章专题视频专题问答1问答10问答100问答1000问答2000关键字专题1关键字专题50关键字专题500关键字专题1500TAG最新视频文章推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37视频文章20视频文章30视频文章40视频文章50视频文章60 视频文章70视频文章80视频文章90视频文章100视频文章120视频文章140 视频2关键字专题关键字专题tag2tag3文章专题文章专题2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章专题3
当前位置: 首页 - 科技 - 知识百科 - 正文

浅析Prototype的模板类Template_prototype

来源:动视网 责编:小采 时间:2020-11-27 21:01:37
文档

浅析Prototype的模板类Template_prototype

浅析Prototype的模板类Template_prototype:用过Prototype的人都知道,里面有个类叫做Template,用法示例如下: 代码如下: var str = '#{what} may have gone, but there is a time of #{how}'; var object = { what : 'Swallows', how : 'return' } v
推荐度:
导读浅析Prototype的模板类Template_prototype:用过Prototype的人都知道,里面有个类叫做Template,用法示例如下: 代码如下: var str = '#{what} may have gone, but there is a time of #{how}'; var object = { what : 'Swallows', how : 'return' } v


用过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是一个嵌套的对象,我们该怎么替换?
即:
代码如下:

var object = {
what : {
name : 'Swallows'
},
how : 'return'
}


最开始的#{what}肯定不能满足要求,所以我们硬性规定,如果要实现嵌套对象的替换,写作#{what.name}或者#{what[name]}。

所以最开始的例子可以写作:
代码如下:
输出:'Swallows may have gone, but there is a time of return'


源码里面有个正则var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/;就是用来实现这个目的的。依次类推,任何深层次的嵌套都可以实现。

要做替换,我们最核心的就是要有一个替换字符的方法,源码里面用的是gsub,下面给出一个gsub的最简版本:
代码如下:

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;
}


这个调用方法和原理跟我前面涉及的replace类似,基本可以互换。http://www.cnblogs.com/xesam/archive/2011/12/05/2276783.html
代码如下:
输出there is a time ofdemo

下面回到Template来,基本要求:有类有方法
代码如下:

var Template = function(template, pattern){
this.template = template.toString();
this.pattern = pattern || Template.Pattern;
};
Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
Template.prototype.evaluate = function(object){}


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有一个嵌套调用的情况,不过意思都一样,最后丢回一个函数就可以了。

文档

浅析Prototype的模板类Template_prototype

浅析Prototype的模板类Template_prototype:用过Prototype的人都知道,里面有个类叫做Template,用法示例如下: 代码如下: var str = '#{what} may have gone, but there is a time of #{how}'; var object = { what : 'Swallows', how : 'return' } v
推荐度:
标签: 模板 te 浅析
  • 热门焦点

最新推荐

猜你喜欢

热门推荐

专题
Top