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

鸣谢: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的延迟加载的机理——动态代理。

 

posted @ 2015-11-18 16:53  Tom1997  阅读(1974)  评论(1编辑  收藏  举报