学习源码,痛苦又快乐的过程。
自己感觉,虽然EXT的模板模型和设计模式的模板模式的实现大相径庭,但它们思想都是一样的,把不变的部分与变化的部分相分离,以便不变的部分可以很好的复用。
来个小例子,比如某工业大学需要一个条幅,为了减缩支出,这个条幅需要是能反复使用的,也就是说,其上面的字是可以来回改的,但其打底的红布是不变的。
Ext扩展了原生String,添加了format这个静态方法,看看其源码。
很容易理解,就是把第一个参数(字符串)中与{\d+}({0},{1}......)匹配的所有字符串依次替换成args[1],args[2]....
这样就把变与不变相分离了。
这个函数的能力太有限了,如果想对变的部分在插入时做些处理,这个函数显然无能为力。
EXT提供了俩个模板类
Ext.Template,Ext.util.Xtemplate。
先来看看Ext.Template类,它的实例方法非常的多,对于我来说也非常难懂,先关注其重要的2点。
先来看看这个类本身。
js的函数真的是非常繁杂的东西,它即可以当成一个对象的方法,又可以是本身的唯一的构造方法,同时它本身又是一个对象。
我理解的是,我们生成一个此类的对象时,和直接调用这个函数唯一的区别就是,new会返回一个此类的对象。
当我们new一个这个模板的对象,这个构造器大概做的事情就是分传参的不同情况,给它的对象添加一个html字符串,并且可以添加一个或多个函数或属性,这些函数,属性是非常有用的,它被用来当做格式化要插入的数据,它可以是自定义的(this.XX),也可以是Ext.util.format类的函数。
属性呢?它主要是一些解析过程的配置参数,如complied,disableFormat等
当我们有了这个模板实例后,就可以调用它的实例方法,此时就会应用动态数据把变的部分传入,此时还会调用它的格式化函数来格式化动态数据,并且显示到我们想让它出现的地方。
拿append实例方法来说明。
append : function(el, values, returnElement){
return this.doInsert('beforeEnd', el, values, returnElement);
},
可以看到此时又调用了实例方法-doInert
doInsert : function(where, el, values, returnEl){
el = Ext.getDom(el);
var newNode = Ext.DomHelper.insertHtml(where, el, this.applyTemplate(values));
return returnEl ? Ext.get(newNode, true) : newNode;
},
又可以看出,doInset主要把是已经生成为HTML字符串定位到哪里(把其放到DOM文档的哪里,这个HTML字符串是由 applyTemplate(values)生成的),而传入动态数据和格式化传入数据,并且返回这个已经填充好内容的具体模板(HTML字符串)的功能是applyTemplate(values)完成
来看看这个applyTemplate(values),嗯,这个函数又碉堡了,现在还看得很模糊,因为正则表达式比较学得比较烂,尤其fn那里,Jack Slocum。。。。
自己感觉,虽然EXT的模板模型和设计模式的模板模式的实现大相径庭,但它们思想都是一样的,把不变的部分与变化的部分相分离,以便不变的部分可以很好的复用。
来个小例子,比如某工业大学需要一个条幅,为了减缩支出,这个条幅需要是能反复使用的,也就是说,其上面的字是可以来回改的,但其打底的红布是不变的。
var s='<div style="width:200px;height:20px;background-color:red"><span style="color:black">{0}</span></div>';
var c=String.format(s,'欢迎XX莅临我校,吃好喝好');
document.write(c);
var c=String.format(s,"热烈庆祝我校清考业务收入创新高');
document.write(c);
Ext扩展了原生String,添加了format这个静态方法,看看其源码。
format : function(format){
var args = Ext.toArray(arguments, 1);
return format.replace(/\{(\d+)\}/g, function(m, i){
return args[i];
});
}
很容易理解,就是把第一个参数(字符串)中与{\d+}({0},{1}......)匹配的所有字符串依次替换成args[1],args[2]....
这样就把变与不变相分离了。
这个函数的能力太有限了,如果想对变的部分在插入时做些处理,这个函数显然无能为力。
EXT提供了俩个模板类
Ext.Template,Ext.util.Xtemplate。
先来看看Ext.Template类,它的实例方法非常的多,对于我来说也非常难懂,先关注其重要的2点。
先来看看这个类本身。
Ext.Template = function(html){
var me = this,
a = arguments,
buf = [];
if (Ext.isArray(html)) {
html = html.join("");
} else if (a.length > 1) {
Ext.each(a, function(v) {
if (Ext.isObject(v)) {
Ext.apply(me, v);
} else {
buf.push(v);
}
});
html = buf.join('');
}
js的函数真的是非常繁杂的东西,它即可以当成一个对象的方法,又可以是本身的唯一的构造方法,同时它本身又是一个对象。
我理解的是,我们生成一个此类的对象时,和直接调用这个函数唯一的区别就是,new会返回一个此类的对象。
当我们new一个这个模板的对象,这个构造器大概做的事情就是分传参的不同情况,给它的对象添加一个html字符串,并且可以添加一个或多个函数或属性,这些函数,属性是非常有用的,它被用来当做格式化要插入的数据,它可以是自定义的(this.XX),也可以是Ext.util.format类的函数。
属性呢?它主要是一些解析过程的配置参数,如complied,disableFormat等
当我们有了这个模板实例后,就可以调用它的实例方法,此时就会应用动态数据把变的部分传入,此时还会调用它的格式化函数来格式化动态数据,并且显示到我们想让它出现的地方。
拿append实例方法来说明。
append : function(el, values, returnElement){
return this.doInsert('beforeEnd', el, values, returnElement);
},
可以看到此时又调用了实例方法-doInert
doInsert : function(where, el, values, returnEl){
el = Ext.getDom(el);
var newNode = Ext.DomHelper.insertHtml(where, el, this.applyTemplate(values));
return returnEl ? Ext.get(newNode, true) : newNode;
},
又可以看出,doInset主要把是已经生成为HTML字符串定位到哪里(把其放到DOM文档的哪里,这个HTML字符串是由 applyTemplate(values)生成的),而传入动态数据和格式化传入数据,并且返回这个已经填充好内容的具体模板(HTML字符串)的功能是applyTemplate(values)完成
来看看这个applyTemplate(values),嗯,这个函数又碉堡了,现在还看得很模糊,因为正则表达式比较学得比较烂,尤其fn那里,Jack Slocum。。。。
Ext.apply(Ext.Template.prototype, {
applyTemplate : function(values){
var me = this,//模板实例
useF = me.disableFormats !== true,//模板对象的一个属性判断可否数据可否格式化
fm = Ext.util.Format,
tpl = me;
if(me.compiled){//先不管这段代码,以后讨论,它是为提高性能的
return me.compiled(values);
}
function fn(m, name, format, args){//内联函数,作为String.replace的回调函数,所以其参数格式是固定的
if (format && useF) {//模板实例里是否有format函数,
if (format.substr(0, 5) == "this.") {//如果是自定义的格式化参数
return tpl.call(format.substr(5), values[name], values);//执行
} else {//处理Ext.util.Format里的函数
if (args) {//解析对应Ext.util.Format传入的参数
var re = /^\s*['"](.*)["']\s*$/;
args = args.split(',');
for(var i = 0, len = args.length; i < len; i++){
args[i] = args[i].replace(re, "$1");
}
args = [values[name]].concat(args);
} else {
args = [values[name]];
}
return fm[format].apply(fm, args);//执行
}
} else {
return values[name] !== undefined ? values[name] : "";
}
}
return me.html.replace(me.re, fn);//替换变的部分
},