• 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: '示例窗口,
         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的延迟加载的机理——动态代理。

  • 相关阅读:
    [转]zookeeper-端口说明
    ACM-ICPC(9/26)
    ACM-ICPC(9/25)
    Linux的文件权限与目录配置
    Uva 11468 AC自动机或运算
    Uva 11922 Splay
    HDU 6214 最小割边
    Uva 10559 消除方块
    HDU 6194 后缀数组
    Uva 11491 暴力贪心
  • 原文地址:https://www.cnblogs.com/wql025/p/4975069.html
Copyright © 2020-2023  润新知