您的位置:首页 > Web前端 > JavaScript

Extjs-4.2.1(二)——使用Ext.define自定义类

2015-11-18 16:53 204 查看
鸣谢:http://www.cnblogs.com/youring2/archive/2013/08/22/3274135.html

--------------------------------------------------------------------------

本篇博客主要介绍了Etxjs如何自定义类的,以及Extjs的继承、属性的封装,这类似于java语言的继承、封装的特点。此外,在java语言中,分层是重要的思想,如类的定义与创建其实例并调用方法一般都是分别写在不同的java文件中,javascript语言由于没有类的概念,因此总是所有的代码写在一个js文件中,而Extjs则不同,它与java语言一样具有面向对象的特性,在本博客中所介绍的Extjs的动态加载描述了Extjs是如何将类的定义与创建类的实例及调用方法进行分层的。

一、什么是define?

define是Extjs的一个方法,用于定义一个类或覆盖。详情见API:http://extjs-doc-cn.github.io/ext4api/#!/api/Ext

二、ExtJS 中自定义类

在ExtJS中,定义一个Person类:

Ext.onReady(function(){
Ext.define('Person',{
name:'wang',
say:function(){
alert('hi,'+this.name);
}

})
var obj = new Person();
obj.say();
})


在这段代码中,我们使用了Ext.define方法自定义一个Person类,它具有Name,具有Say 方法,运行结果如下:



在上面的类中,name属性被赋了一个指定的值,显然,除了静态属性,在类中的属性仅需被声明,在创建实例时进行赋值,这就需要构造函数了。看下面的代码:

Ext.onReady(function(){
Ext.define("Person2", {
//定义、初始化成员属性
Name: '',
Age: 0,
//定义成员方法
Say: function (msg) {
Ext.Msg.alert(this.Name + " Says:", msg);
},
//定义构造函数
constructor: function (name, age) {
this.Name = name;
this.Age = age;
}

});
var Tom = new Person2("Tom", 26);
Tom.Say("Hello");
})


运行结果:



三、ExtJS 中类的继承

ExtJS 允许对现有的类进行扩展,其扩展可以通过继承来实现。接下来我们就对刚刚使用ExtJS定义的Person2类进行继承,定义一个Developer类,它继承自Person2,同时还拥有Coding方法,代码如下:

/**
* 此js演示了Etxjs类的继承
*/
Ext.onReady(function(){

//基类
Ext.define("Developer", {
extend: 'Person2',//继承
Coding: function (code) {
Ext.Msg.alert(this.Name + " 正在编码..", code);
},
constructor: function(){
this.callParent(arguments);
}
});

var Bill = new Developer("Bill", 26);
Bill.Coding("int num1 = 0; ");
})


从代码中可看出,ExtJS 使用 extend来实现继承。我们为Developer 类添加了Coding 方法,这是我们对Person类进行的扩展。在构造函数中,通过调用this.callParent 方法,实现对属性的初始化。需要说明的是,如果此处只调用了父类的构造方法,则可以省略掉,ExtJS 会自动为我们调用父类的构造函数。所以我们此处的代码可以进行简化:

/**
* 此js演示了Etxjs类的继承
*/
Ext.onReady(function(){

//基类
Ext.define("Developer", {
extend: 'Person2',//继承
Coding: function (code) {
Ext.Msg.alert(this.Name + " 正在编码..", code);
}
});

//基类在new实例时如果在其类中没有定义构造方法,则调用其父类的构造方法。
var Bill = new Developer("Bill", 26);
Bill.Coding("int num1 = 0; ");
})


需要注意的是:1.如果你在子类中使用了构造函数,ExtJS 则不会再自动调用父类的构造函数;2.像java导包一样,在html中要导入父类的js文件,代码如下:

<!-- 导入父类 -->
<script type="text/javascript" src="../js/define/define2.js"></script>
<script type="text/javascript" src="../js/define/define3.js"></script>


运行结果:



四、ExtJS 中类的选项 - config

首先看一个例子,我们在ExtJS中定义一个Window对象,代码如下:

var win = Ext.create("Ext.window.Window", {
title: '示例窗口,
width: 300,
height: 200
});
win.show();


在上面的代码中,我们通过Ext.create方法创建了一个Window 对象,Ext.create 方法的第一个参数是类名,第二个参数是类的选项,它是一个JSON格式的对象,用来初始化Window对象。我们的窗口运行如下:



试想一下,如果我们的类中有几十个属性,那么我们使用构造函数就要传入几十个参数来对它完成初始化,这是一件很恐怖的事情。还好ExtJS 为我们提供了这种便利,我们可以在定义类的时候为它添加配置项——config,它是Extjs的属性包装器,为属性提供get和set方法。

我们来修改Person类,使它可以通过config初始化:

/**
* define-config
* 此js演示了在定义的类中将类的成员属性放在config中并且如何实例化对象的。
*/
Ext.onReady(function(){
Ext.define("Person", {
config: {
Name: '',
Age: 0
},
Say: function (msg) {
Ext.Msg.alert(this.Name + " Says:", msg);
},
Say2: function (msg) {//在方法中,“this.config.属性名”和“this.属性名”的形式都可以调用成员属性。
Ext.Msg.alert(this.config.Name+","+this.Age + " Says:", msg);
},
constructor: function (config) {
this.initConfig(config);
}
});

//注意:因为在Person类中将成员属性放进了config中,因此已不能用new的方式进行实例化了。
var Jack = new Person('Jack',28);
//    Jack.Say('hi');
//    alert(Jack.getAge());

//使用Ext的create方法创建并返回一个实例
var Tom = Ext.create("Person", {
Name: 'Tom',
Age: 26
});
Tom.Say("Hello");
//    alert(Tom.getAge());//26 注:“Tom.config.Age”、“Tom.Age”都可以得到Age的值

//使用Ext自动生成的set、get方法设置、访问实例属性
Tom.setAge(18);//注:“Tom.Age=18”也可以——这是js赋值的方法
//    alert(Tom.getAge());//18 注:“Tom.Age”也可以——这是js取值的方法
})


我们在类的定义中添加了config项,将需要在配置中完成的属性添加在里面,而在构造函数中,我们通过调用this.initConfig方法完成对config的初始化;在定义Person类对象的时候,使用Ext.create方法,传入类名Person以及配置项,运行结果:



五、ExtJS 中类的别名 - alias

在我们查看ExtJS API 的时候,在左侧常会有这样的说明:



红色方框圈出的部分是这个类的别名,它对应类的全称是 Ext.window.Window,由此可以看出别名更加简单,容易记忆和书写。我们在实例化类的时候,可以使用别名来替代类名全称,例如我们之前定义的win对象,他的代码可以修改为:

/**
* define-alias
* 此js演示了利用"alias"给定义的类起别名。
*/
Ext.onReady(function(){
Ext.define("vo.Person", {
config: {
Name: '',
Age: 0
},
alias:"Person",//给定义的类起个别名
Say: function (msg) {
Ext.Msg.alert(this.Name + " Says:", msg);
},
Say2: function (msg) {//在方法中,“this.config.属性名”和“this.属性名”的形式都可以调用成员属性。
Ext.Msg.alert(this.config.Name+","+this.Age + " Says:", msg);
},
constructor: function (config) {
this.initConfig(config);
}
});

//使用Ext的create方法创建并返回一个实例
var Tom = Ext.create("Person", {
Name: 'Tom',
Age: 26
});
Tom.Say("Hello");

})




六、ExtJS 中的动态加载

在Ext.create 方法的介绍中,有这样一段描述:



它的意思是:如果Ext.loader 可用,且类还没有被定义,它将试图通过同步加载来加载类。

接下来我们来试试类动态加载的功能。我们的类vo.Person 类的位置是:



下面是Person.js的代码:

/**
* define
* 此js定义一个Person类
*/

Ext.define("vo.Person", {
config: {
Name: '',
Age: 0
},
alias:"Person",//给定义的类起个别名
Say: function (msg) {
Ext.Msg.alert(this.Name + " Says:", msg);
},
Say2: function (msg) {//在方法中,“this.config.属性名”和“this.属性名”的形式都可以调用成员属性。
Ext.Msg.alert(this.config.Name+","+this.Age + " Says:", msg);
},
constructor: function (config) {
this.initConfig(config);
}
});


下面是在HTML中需要引用的js(define6.js)代码:

/**
* define-alias
* 此js演示了Ext的动态加载
*/
//js获取项目根路径,如:http://localhost:8081/extjsTest1
function getRootPath(){
//获取当前网址,如: http://localhost:8081/extjsTest1/define/define6.jsp var curWwwPath=window.document.location.href;
//获取主机地址之后的目录,如: extjsTest1/define/define6.jsp
var pathName=window.document.location.pathname;
var pos=curWwwPath.indexOf(pathName);
//获取主机地址,如: http://localhost:8081 var localhostPaht=curWwwPath.substring(0,pos);
//获取带"/"的项目名,如:/extjsTest1
var projectName=pathName.substring(0,pathName.substr(1).indexOf('/')+1);
return(localhostPaht+projectName);
}

Ext.onReady(function(){

Ext.Loader.setConfig({
enabled:true,
paths:{
vo: getRootPath()+"/js/vo"//告诉Extjs命名空间“vo”的路径
}
})

/**
* 在Extjs创建vo.Person的实例Tom时发现该类没有被定义,因此它会加载命名空间vo指定路径下的Person.js,
* 这就是Extjs的动态加载。
*/
var Tom = Ext.create("vo.Person", {//注意:使用动态加载,应使用类的全名,如果使用别名Extjs无法找到正确的路径。
Name: 'Tom',
Age: 26
});
Tom.Say("Hello");

})


在完成Loader 的配置以后,我们就可以移除掉对Person.js的引用了,下面是HTML引用文件:

<link rel="stylesheet"  type="text/css" href="../ext-4.2.1/resources/ext-theme-neptune/ext-theme-neptune-all.css">

<script type="text/javascript" src="../ext-4.2.1/ext-all.js"></script>
<script type="text/javascript" src="../ext-4.2.1/locale/ext-lang-zh_CN.js"></script>

<script type="text/javascript" src="../js/define/define6.js"></script>


可以看到,上面并没有引用项目中的"../js/Vo/Person.js"这个js文件,运行结果:



另外,我们还可以手动的加载Person.js,代码如下:

/**
* define-alias
* 此js演示了Ext的动态加载
*/

//js获取项目根路径
function getRootPath(){
var curWwwPath=window.document.location.href;
var pathName=window.document.location.pathname;
var pos=curWwwPath.indexOf(pathName);
var localhostPaht=curWwwPath.substring(0,pos);
var projectName=pathName.substring(0,pathName.substr(1).indexOf('/')+1);
return(localhostPaht+projectName);
}

Ext.onReady(function(){

Ext.Loader.setConfig({
enabled:true,
paths:{
vo: getRootPath()+"/js/vo"//告诉Extjs命名空间“vo”的路径
}
})

//加载Person.js
Ext.require("vo.Person");

var Tom = Ext.create("Person", {//fail:使用Ext.require方法加载Person.js无法用vo.Person的别名Person创建实例
Name: 'Tom',
Age: 26
});
Tom.Say("Hello");

})


但可惜的是,目前得到的是失败的结果,运行,在谷歌浏览器出现以下错误:



说明Ext.require没有正确加载Person.js

小结:Extjs的动态加载不仅实现了分层设计的思想,而且对于提高系统性能有重要的意义——这类似于hibernate的延迟加载的机理——动态代理。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: