浅析Prototype的模板类 Template

时间:2021-05-18

用过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://p]还是一个对象,那么抱歉,加班继续干吧。

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

声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。

相关文章