本教程基于Ext的模板引擎展开详述,亦是对 Shea Frederick“模板入门”教程一文的补充。假设读者已经初步接触过模板(Templates),和格式化函数的基本语法为“{VARIABLE:[(可选的参数)]}”。
正式开始
假设我们打算从一变量中,打印出内容,但当中的内容有可能会占用过多的空间。对于这种情况,通过的办法是对该内容截取,限制在50个英文字符内,然后做成连接让用户点击后观察全文。函数"ellipsis" 的功能正是这样,可限制在任意字符数内。另外,在截取字符串的后面,该函数还会加上“...“,以示实际的内容还有更多。
一个模板如下示
通过处理,其中有47个字符是属于内容本身的,另外三个字符是”...“,一共50个字符。
这是一份可用于模板格式化函数的列表:
· ellipsis(length) - 对大于指定长度部分的字符串,进行裁剪,增加省略号(“...”)的显示。适用于只显示前N位的字符,然后提供详细页面的场合。
· undef -检查一个值是否为underfined,如果是的转换为空值
· htmlEncode - 转换(&, <, >, and ') 字符
· trim - 对一段文本的前后多余的空格裁剪
· substr(start, length) - 返回一个从指定位置开始的指定长度的子字符串。
· lowercase - 返回一个字符串,该字符串中的字母被转换为小写字母。
· uppercase - 返回一个字符串,该字符串中的字母被转换为大写字母。
· capitalize - 返回一个字符串,该字符串中的第一个字母转化为大写字母,剩余的为小写。
· usMoney - 格式化数字到美元货币。如:$10.97
· date[(format)] - 将一个日期解析成为一个特定格式模式的日期。如日期字符串不输入,默认为“月/日/年”
· stripTags - 剥去变量的所有HTML标签
您亦可以创建自定义的格式化函数,具体做法是,在模板的实例上加入新的方法,继而在模板上调用,格式化的函数应该像这样的:{VARIABLE:this.}"
这是一个简单的实例,对模板实例加入一个"yesNoFormat "的新函数。yesNoFormat 与ColdFusion转换”truthy“函数相类似 ,如果是真的输出"Yes",假的输出"No"。
var testCustomTpl = new Ext.Template('
User: {username} IsRevoked: {revoked:this.yesNoFormat}
');
testCustomTpl.yesNoFormat = function(value) {
return value ? 'Yes' : 'No';
};
testCustomTpl.append(document.body, {username: 'aconran', revoked: 1});
下一步
关于怎么学好EXT这个框架我的看法是,在您熟悉的IDE中打开源码进行阅读。保证阁下一定会收获不少技巧和写代码的好习惯,而且极有可能发现新的大陆,还是没有归档的。熟悉模板Templates的简单用法和格式化功能后,就可进入下一步的学习:MasterTemplates。 MasterTemplates提供了处理”子模板“的功能,以方便从数据库循环数据,同时亦包含模板(Templates)的所有功能。
事件处理
在Javascript中,你将不得不经常进行事件的处理。这有时很难顺利进行,因为你需要进行不同的跨浏览器标准化事件处理。而ExtJs使得处理事件变得非常容易,有时候甚至还富于乐趣(!)。
想象一下这样一个例子,当用户点击一个链接时,你想向他显示一则警告信息。请继续往下看,因为在开始处理事件前你也许想知道更多。
var el = Ext.get('somelink');
el.on('click', function(){
alert('you click on a link');
});
注意,在这里我们使用了一个匿名处理函数。另外,你应该在DOM初始化后才执行上述代码(使用Ext.onReady()方法)
好了,我们刚刚学习了最基础的事件处理。让我们看看其他一些我们能做的事。默认情况下,处理函数内的作用域是你绑定事件的元素。
var el = Ext.get('somelink');
el.on('click', function(){
alert(this.id); // 这里将显示'somelink'
});
注意this不是Ext Element对象。如果你想使用Ext的方法你必须使用"var el = Ext.get(this);"
但如果我们想要改变处理函数内的作用域呢?你可以把那个对象作为作用域参数。
function onClick = function(){
alert(this.someProperty); // 这里将显示'someValue'
};
var scope = {
someProperty : 'someValue'
}
var el = Ext.get('somelink');
el.on('click', onClick, scope);
提示:更多关于作用域的信息请参见这里
在前面的例子中我们看到了如何改变处理函数内的作用域。但如果我们仍然想访问(与之相绑定的)元素呢?我们可以使用传递给处理函数的参数来进行操作。
function onClick = function(ev, target){
alert(this.someProperty); // 这里将显示'someValue'
alert(target.id); // 这里将显示'somelink'
};
var scope = {
someProperty : 'someValue'
}
var el = Ext.get('somelink');
el.on('click', onClick, scope);
如你所见,在这个例子中我们使用了第二个参数(target)。第一个参数是Ext Event对象,我们可以使用此对象来做很多事情。
类设计
Javascript与其他的面向对象语言不同,如C++,Java或PHP等。它并不是基于类的,而是基于原型的一种语言。
在Javascript中创建一个类是非常容易的:
var myObject = {
aVar: 15,
aMethod: function() {
alert("I'm a method of the object myObject." + "aVar: " + this.aVar);
}
}
你不必通过定义一个类然后实例化该类来创建一个对象。我们在这里使用了一个对象构造器。它满足了使用单个对象的场合。如果我们需要使用同一个类型的多个对象,我们必须使用一个构造器函数和new关键字。
在Javascript中没有类的概念,但是构造器是存在的。你可以编写一个函数,然后通过new关键字来创建一个对象。
// 首先,我们为我们的类定义一个空的构造器
function myClass() {
this.aVar = 15;
this.aMethod = function() {
alert("I'm a method of the object myObject.");
}
}
// 创建类的实例
var A = new myClass();
// 显示 15
alert(A.aVar);
// 第二个实例
var B = new myClass();
你必须使用prototype对象:
// 我们定义了一个prototype对象的一个方法
myClass.prototype.sharedMethod = function() { alert("I'm a shared method") }
// 显示我们的信息
A.sharedMethod();
// 相同的信息
B.sharedMethod();
There is no method named sharedMethod in the myClass definition. Javascript looks for a method with this name in the prototype object of myClass and calls it if it exists. 在myClass定义中并没有一个名为sharedMethod的方法。Javascript会在myClass相关联的prototype对象中寻找与该方法名相同的方法,如果存在的话,Javascript则调用该方法。
表单组件入门
我建议下载用于这个例子的一段程序,这样可能对你有一些帮助。你也可以找一个有效的例子。
表单体
首先要做的第一件事就是创建一个表单体,这相当于在HTML中书写一个 <form></form>标识。
var form_employee = new Ext.form.Form({
labelAlign: 'right',
labelWidth: 175,
buttonAlign: 'right'
});
创建表单字段
表单示例由name、title、hire_date和active四个表单字段构成。开头的两个表单字段name和title,只是简单的文本字段,我们会用TextField方法来创建它们。
重要的配置选项是name,定义该选项与HTML中定义一个表单字段名几乎一样。
var employee_name = new Ext.form.TextField({
fieldLabel: 'Name',
name: 'name',
width:190
});
var employee_title = new Ext.form.TextField({
fieldLabel: 'Title',
name: 'title',
width:190
});
跟着的hire_date字段是一个日期字段,我们会用DateField方法来创建,它会为我们弹出一个别致的日期选择器来让我们选择日期。
format配置选项被用来为PHP指定日期格式标准(PHP的日期格式)。日期格式字符串的调整须与你所用的日期格式相匹配。
var employee_hire_date = new Ext.form.DateField({
fieldLabel: 'Hire Date',
name: 'hire_date',
width:90,
allowBlank:false,
format:'m-d-Y'
});
最后一个表单元素active是一个布尔值,我们使用Checkbox方法来创建。
var employee_active = new Ext.form.Checkbox({
fieldLabel: 'Active',
name: 'active'
});
完成表单
现在,我们把表单里的所有表单字段加入到fieldset中去。当然了,如果你想在fieldset的外面进行,可以选择使用add方法。
form_employee.fieldset(
{legend:'Employee Edit'},
employee_name,
employee_title,
employee_hire_date,
employee_active
)
最后,最不能少的就是submit按钮,它与一小段点击时进行错误检测的代码块一起被addButton方法加进来。调用render方法,传入div标识的“id”,然后在网页的div里把表单显示出来。
form_employee.addButton('Save', function(){
if (form_employee.isValid()) {
Ext.MessageBox.alert('Success', 'You have filled out the form correctly.');
}else{
Ext.MessageBox.alert('Errors', 'Please fix the errors noted.');
}
}, form_employee);
form_employee.render('employee-form');
下一步
虽然本教程让你懂得了如何去创建一个表单,但创建出来的表单什么事情也干不了。就像一部没有引擎的小汽车——它看起来可能很漂亮,但不能让你走得更远。
为一个表单填充或提交数据
这个教程使用了在表单入门教程中使用过的 雇员信息编辑表单。如果你仍然不熟悉如何创建一个表单,你可以首先看一下这个例子。我建议下载用于这个例子的一段程序,这样可能对你有一些帮助。你也可以找一个有效的例子。
我们将经历使用表单的整个过程,从最初的从服务器获取数据填入表单,到将数据返回给服务器。在后端我使用PHP和MySQL, 然而这个例子对于PHP和MySQL来说并不是特殊的,而是只要求你能够从你的服务器读取和输出JSON数据。
让我们开始吧
首先我们必须设置表单的url, 这是一个能获得POST数据并将其写进我们的数据库的PHP脚本.
var form_employee = new Ext.form.Form({
...
url:'forms-submit-process.php',
...
});
我们的数据包含5个字段:id, name, title, hire_date和active,这些字段可以被取回并放置到一个数据存储对象(Store)中。
以下的程序构造了一个数据存储对象,在这个时候没有数据被取回,我们的数据代理(Proxy)对象提交到一个PHP脚本,用来取回数据库id为14的行 并将它转换成一个JSON字符串。
employee_data = new Ext.data.Store({
proxy: new Ext.data.HttpProxy({url: 'forms-submit-getdata.php?id=14'}),
reader: new Ext.data.JsonReader({},[ 'id', 'name', 'title', 'hire_date', 'active']),
remoteSort: false
});
接下来要做的是设定我们的事件监听者来监察什么时候数据被载入, 这个将保证我们不会在数据被载入之前填入表单。
employee_data.on('load', function() {
// data loaded, do something with it here...
});
当数据被载入后,我们可以取回数据并用setValue方法将其填入表单。这里我们用getAt(0) 从我们的数据存储对象里重新取回第一行数据(行zero)。
注意:这里使用的表单和表单字段在getting started tutorial中有定义和解释。
employee_name.setValue(employee_data.getAt(0).data.name);
employee_title.setValue(employee_data.getAt(0).data.title);
employee_hire_date.setValue(employee_data.getAt(0).data.hire_date);
employee_active.setValue(Ext.util.Format.boolean(employee_data.getAt(0).data.active));
我们将要创建提交按钮并添加到表单,记得给来源于表单字段的POST数据设定扩展参数。你将会发现通过行确定字段(id)对于让php脚本找到需要更新的行非常有用,同时为了更好的判断,还需要一个action判定。
我还使用isValid参数来保证表单在提交前符合每一个字段的要求。
form_employee.addButton('Save', function(){
if (form_employee.isValid()) {
form_employee.submit({
params:{
action:'submit',
id:employee_data.getAt(0).data.id
},
waitMsg:'Saving...'
});
}else{
Ext.MessageBox.alert('Errors', 'Please fix the errors noted.');
}
}, form_employee);
form_employee.render('employee-form');
读取我们的数据
现在我们来读取数据
employee_data.load();
这样真的能够惊人简单的创建一个可用的表单,与成对的服务器段脚本接合,就能够将数据从数据库获取并写入修改后的数据。这些服务端脚本可以简单到只需几行而已。
EXT中的继承
Ext提供了这样的一个实用函数 Ext.extend (API 参考) 在EXT框架中实现类继承的机制。这赋予了你扩展任何JavaScript基类的能力,而无须对类自身进行代码的修改(这里通常指的是子类,或是从它继承的,一个基类)扩展Ext组件这是个较理想的方法。
要从一个现有的类创建出一个新类,首先要通过一个函数声明新类的构造器,然后调用新类属性所共享的扩展方法。这些共享的属性通常是方法,但是如果要在实例之间共享数据(例如,Java中的静态类变量),应该也一同声明。
JavsScript并没有提供一个自动的调用父类构造器的机制,所以你必须通过属性superclass在你的构造器中显式调用父类。第一个参数总是this,以保证构造器工作在调用函数的作用域。
MyNewClass = function(arg1, arg2, etc) {
// 显式调用父类的构造函数
MyNewClass.superclass.constructor.call(this, arg1, arg2, etc);
};
Ext.extend(MyNewClass, SomeBaseClass, {
theDocument: Ext.get(document),
myNewFn1: function() {
// etc.
},
myNewFn2: function() {
// etc.
}
});
下面的一个例子是Ext的实际案例,用于可缩放,拖动元素,X、Y的坐标值指定了对象可在垂直、水平方向拖动的距离。
// 创建新类的构造函数
Ext.ResizableConstrained = function(el, config){
Ext.ResizableConstrained.superclass.constructor.call(this, el, config);
};
// 扩展基类
Ext.extend(Ext.ResizableConstrained, Ext.Resizable, {
setXConstraint : function(left, right){
// 得到父类的属性dd和setXConstraint的引用
this.dd.setXConstraint(left, right);
},
setYConstraint : function(up, down){
// 得到父类的属性dd和setYConstraint的引用
this.dd.setYConstraint(up, down);
}
});
// 创建新类的实例
var myResizable = new Ext.ResizableConstrained('resize-el', {
width: 200,
height: 75,
minWidth:100,
minHeight:50,
maxHeight:150,
draggable:true
});
//调用新方法
myResizable.setYConstraint(0,300);
myResizable.setXConstraint(0,300);
按照直白语言,你可以把上面的代码理解成为:”Ext.ResizableConstrained 扩展了Ext.Resizable并实现了这些方法"。