Ext js 6 - Class System

Class System

Overview

我们可以搭建测试代码, 不需要使用Sencha cmd

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
    <link href="./build/classic/theme-classic/resources/theme-classic-all.css" rel="stylesheet" />
    <script src="./build/ext-all.js"></script>
    <script>
        Ext.define("My.sample.Person", {
            name: 'Unknow',
            constructor: function(name){
                if (name) {
                    this.name = name;
                }
            },
            eat: function(foodType){
                alert(this.name + " is eating: " + foodType);
            }
        })
        var bob = Ext.create("My.sample.Person", 'Bob');
        bob.eat("Salad");
    </script>
</head>
<body>
<div id="helloWorldPanel"></div>
</body>
</html>

命名规则

类名

类名只可以包含字母和数字字符,使用数字是允许的,但不鼓励使用,除非这个类名,要表示的是专有名词,比如
base64. 不能使用下划线,连接字符,或其它非non-alphanumeric

  • MyCompany.useful_util.Debug_Toolbar 这是不允许的
  • MyCompany.util.Base64 可以使用

类名应该在一个顶级命名空间(唯一)之后,比如

MyCompany.data.CoolProxy
MyCompany.Application

开始的命名空间和实际的类名都应该为驼峰命名法(每个单词首字母大写), 其它的都应该小写

MyCompany.form.action.AutoLoad

实际类名如果有缩略词,也应该遵循驼峰命名法, 比如下面的情形

  • Ext.data.JSONProxy应该写为Ext.data.JsonProxy
  • MyCompary.parser.HTMLParser写为MyCompany.util.HtmlParser
  • MyCompany.server.HTTP写为MyCompany.server.Http

源文件

类的名字也就表示了它源文件的的路径。所以每个类必须对应一个源文件,比如
* Ext.util.Observable is stored in path/to/src/Ext/util/Observable.js
* Ext.form.action.Submit is stored in path/to/src/Ext/form/action/Submit.js
* MyCompany.chart.axis.Numeric is stored in path/to/src/MyCompany/chart/axis/Numeric.js

path/to/src表示你应用程序的目录,所有的类都应该保存在相同的目录下,并且采用这种方式,方便开发,维护和部署。

方法和变量的命名

  • 这跟类名的命名类似。只能是字母和数字。
  • 方法和变量必须为camelCased(小写开头). 这同样适用于缩略词,比如json, html.

Example

  • 以下是有效的方法名
    • encodeUsingMd5()
    • getHTML() 应该为getHtml()
    • getJSONResponse()应该为getJsonResponse()
    • parseXMLContent()应该为getXmlContent()
  • 以下是有效的变量名
    • isGoodName
    • base64Encoder
    • xmlReader
    • httpServer

属性

  • 类的属性的命名,跟类,变量,方法的命名是一样的。除非它们为静态常量
  • 类的静态属性命名,则全部为大写
    • Ext.MessageBox.YES = “Yes”
    • Ext.MessageBox.NO = “No”
    • MyCompany.alien.Math.PI = “4.13”

类的声明

Ext.define用于创建一个类, 这个方法创建的类,都是Ext.Base的子类, 所以创建的子类都有, callParent, callSuper, initConfig,

getConfig, setConfig, 等方法。 以下是它的基础用法

Ext.define(className, members, onClassCreated);
  • className: 字符串表示的类的名字
  • members: 一个对像,以键和值的方式,表示这个类的成员(变量和方法)
  • onClassCreated 是一个可选的回调函数。当定义的这个类的加载完它的依赖,并且这个类完全创建好后,调用。对于
    异步来说,在很多情况下这非常有用。

    Example

Ext.define('My.sample.Person', {
    name: 'Unknown',

    constructor: function(name) {
        if (name) {
            this.name = name;
        }
    },

    eat: function(foodType) {
        alert(this.name + " is eating: " + foodType);
    }
});

var bob = Ext.create('My.sample.Person', 'Bob');

bob.eat("Salad"); // alert("Bob is eating: Salad");

**Note:我们也可以通过new My.sample.Person创建这个类的实例,但是推荐使用Ext.create方法。 因为它可以让你使用动态加载,
而new则不可以。**

Configuration

新创建的类会从Ext.Class继承一个专有的config属性. Ext.Class主要用于描述一个类,比如alias, config, xtype等。
* config属性指定的配置独立于新建类的其它成员,它完全封闭在config属性中
* 新建类会为每一个config配置创建一个Getter和Setter方法。前题是这些方法没有明确的被定义在新建的类中
* 自动创建的setter方法在设置配置时,会调用apply方法(如果有在类中定义). 如果你在设置新的配置值时,需要重写这个apply方法。如果apply
方法,不返回值,则自动生成的setter方法,不设置这个配置值。同样,还有一个update的方法,这个方法在配置值被设置了不同的值时,被调用。
apply和update的参数为一个新值和一个旧值

对于Ext class的配置,既你定义的类扩展于Ext Component,我们不需要手动的调用initConfig方法,可以直接使用config属性。但对于我们自己创建的类,它会继承Ext.Base
initConfig()依然需要被调用, 否则不会自动生成setter和getter方法, 可以查看Ext.Class config的描述.

Example

Ext.define('My.own.Window', {
   extend: 'Ext.Component',
   /** @readonly */
   isWindow: true,

   config: {
       title: 'Title Here',

       bottomBar: {
           height: 50,
           resizable: false
       }
   },

   applyTitle: function(title) {
       if (!Ext.isString(title) || title.length === 0) {
           alert('Error: Title must be a valid non-empty string');
       }
       else {
           return title;
       }
   },

   applyBottomBar: function(bottomBar) {
       if (bottomBar) {
           if (!this.bottomBar) {
               //如果当前没有设置bottomBar配置,则通过Ext.create创建一个自定义的子类
               //这样它有可以从Ext.Base中继承setConfig, 也可以获得子配置
               //即bottomBar保存的是一个Ext的对像
               return Ext.create('My.own.WindowBottomBar', bottomBar);
           }
           else {
                //查看Ext.Base中的setConfig, 因为当前的bottomBar为一个Ext Base的子类的对像
                //所以可以直接调用它的setConfig, 改变它的值,而不用返回一个新值
               this.bottomBar.setConfig(bottomBar);
           }
       }
   }
});

/** A child component to complete the example. */
Ext.define('My.own.WindowBottomBar', {
   config: {
       height: 10,
       resizable: true
   }
});

以下是代码将看到如何使用configuration创建一个对像

var myWindow = Ext.create('My.own.Window', {
    title: 'Hello World',
    bottomBar: {
        height: 60
    }
});

//由于My.own.Window继承于Ext.Component, 所以它会将创建myWindow中的传递的配置,应用于config中,
//如果是只继承于Ext.Base, 则下面的内容输出undefined, Configuration只能通过setTitle()和getTitle()来使用,也不能使用myWindow.title="Hello World";

alert(myWindow.getTitle()); // alerts "Hello World"

myWindow.setTitle('Something New');

alert(myWindow.getTitle()); // alerts "Something New"

myWindow.setTitle(null); // alerts "Error: Title must be a valid non-empty string"

myWindow.setBottomBar({ height: 100 });

alert(myWindow.getBottomBar().getHeight()); // alerts 100

Statics

静态的成员可以定义在statics config中

xt.define('Computer', {
    statics: {
        instanceCount: 0,
        factory: function(brand) {
            // 'this' in static methods refer to the class itself
            return new this({brand: brand});
        }
    },

    config: {
        brand: null
    }
});

var dellComputer = Computer.factory('Dell');
var appleComputer = Computer.factory('Mac');

alert(appleComputer.getBrand()); // using the auto-generated getter to get the value of a config property. Alerts "Mac"

错误处理与调试

Ext js包含了很多有用的特性,帮助我们调试和处理错误

  • 你可以使用Ext.getDisplayName() 获得任何方法的显示名称, 然后可以应用于抛出错误中.
 throw new Error('['+ Ext.getDisplayName(arguments.callee) +'] Some message here');

如果Ext.define()中定义的类,某个方法抛出了一个错误。那么可以在基于Webkit的浏览器的调用栈,看到这个类和方法名.
这里写图片描述

Ext js常用类

Ext

Ext是一个全局的单例对像,它封装了Sencha库中的所有类,单例以及有用的方法,许多常用的工具函数定义在Ext,
它同样提供了许多其它常用类的快捷键。

以下让我们看看Ext中定义的方法和属性:

application方法

许多应用都是通过Ext.application进行初始化。这个函数加载Ext.app.Application类,并且在页面加载完成之后开始应用程序。

Ext.app.Application是一个类,表示整个的应用。

Ext.application({
  name: 'MyApp',
  extend:'MyApp.Application',
  launch: function() {
  }
});

以上的代码创建了一个全局的变量MyApp.应用程序中所有的类将会在这个唯一的命名空间下,这样可以避免与全局变量的冲突。

define方法

用于创建或覆盖一个类。它接受三个参数,第一个为类名,它为字符串类型,第二个为创建类需要使用到的数据,第三个为创建完后,执行的回调函数.,
因为创建类时,会动态加载依赖的类,这时回调函数就有用了。

Ext.define(name, data, callback)

以下创建一个 Car class

Ext.define('Car', {
  name: null,
  constructor: function(name) {
    if (name) {
      this.name = name;
    }
  },
  start: function() {
    alert('Car started');
  }
});

也可以创建一个继承类

Ext.define('ElectricCar', {
  extend: 'Car',
  start: function() {
    alert("Electric car started");
  }
});

如果你想要替换一个基础类,你可以使用define覆盖原有的方法。

Ext.define('My.ux.field.Text', {
  override: 'Ext.form.field.Text',
  setValue: function(val) {
    this.callParent(['In override']);
    return this;
  }
});

如果你想创建的类,它是一个单例类,你可以使用 singleton属性,它定义在Ext.Class类中

Ext.define('Logger', {
  singleton: true,
  log: function(msg) {
    console.log(msg);
  }
});
//可以直接使用这个类,而不需要使用Ext.create
Logger.log("hello")

create方法

你可以使用以下的方式创建一个类的对像

var myCar = Ext.create('ElectricCar',{
  name: 'MyElectricCar'
});

如果Ext.Loader是允许的,那么 Ext.create 会在ElectricCar这个类不存在的情况下,自动下载相应的Javascript文件。默认情况下,Ext.Loader
是允许的,你也可以配置文件中将Ext.Loader设置为false.

你也可以使用new关键词创建一个实例,但是,如果这个类不存在时,它不会自动加载对应的Javascript文件。

var myCar = new ElectricCar('MyElectricCar');

onReady方法

在页面加载完成时,dom可操作时,调用

Ext.onReady(function(){
  new Ext.Component({
    renderTo: document.body,
    html: 'DOM ready!'
  });
});

在许多情况下,你不需要使用onReady方法。只在一些特定的少有的情况下才需要使用。如果你之前有过jQuery编程,请不要像jQuery那样
经常使用onReady方法

$( document ).ready().

widget方法

当你定义在一个类时,你可以给它一个简短的别名。比如Ext.panel.Panel的一个别名为widget.panel.当你定义了一个widget, 不是在类中指定别名,
你就可以使用xtype表示一个这个类了

当一个container在执行前,没有创建一个组件的时例时,xtype可以用来指定widget的名称,这非常有用。
Ext.widget,它接受一个xtype字符串,而不是类名,用来创建一个widget.

比如,在没有使用widget方法时,创建一个类的时候Ext.panel.Panel的对像

Ext.create('Ext.panel.Panel', {
  renderTo: Ext.getBody(),
  title: 'Panel'
});

然而,你可以使用更简单的方法,创建它的实例

Ext.widget('panel', {  //panel为xtype
  renderTo: Ext.getBody(), //html body
  title: "Panel"
})

以下是使用别名的方法创建一个相同的对像

Ext.create('widget.panel', {
  renderTo: Ext.getBody(),
  title: 'Panel'
});

getClass方法

如果一个类是通过Ext.define定义的,则可以使用getClass方法,返回一个对像的类名。如果类不是通过Ext.define定义的,则返回的为空。

var button = new Ext.Button();
Ext.getClass(button); // returns Ext.Button

getClassName方法

根据引用或者类的对像,返回类的名字(字符串)

Ext.getClassName(Ext.Button); //returns "Ext.Button"

Ext.Base

它是所有Ext的基类。 Ext中所有的类都是继承于Ext.Base. 在这个类中的所有原型和静态成员,都会被其它类所继承。

Ext.Class

这个类是一个低级的工厂类,当在使用Ext.ClassManager创建一个类时使用这个工厂函数。所以,在你的代码中不要直接使用它,
而应该使用Ext.define()

Ext.ClassManager

它用于管理所有的类,并且处理字符串类名到实际类的映射。它通常会在以下几个函数类使用

  • Ext.define
  • Ext.create
  • Ext.widget
  • Ext.getClass
  • Ext.getClassName

Ext.Loader

这个类主要用来动态加载依赖,正常的,使用快捷方法Ext.require替代。当你定义一个类时,最佳的实践时,指定要加载的组件,比如

Ext.require(['widget.window', 'layout.border', 'Ext.data.Connection']);

如果你需要某个空间下的所有组件/类,可以使用通配符

Ext.require(['widget.*', 'layout.*', 'Ext.data.*');

如果要排除,可以使用以下方式

Ext.exclude('Ext.data.*').require('*');

通过这种方式,加载的类是通过异步方式。如果你在定义类时,没有指定加载的类时,则当使用Ext.Create创建这个类的实例时,如果类没有加载时
,类文件将被以同步的方式加载(停止运行,等待文件下载完成)。这会影响一点性能。所以,当你定义你的类时,最好通过Ext.require指定你要加载的类

Class创建过程

在Ext js中每一个class都是Ext.Class类的实例,当我们使用define定义一个类时,实际上我们创建了一个Ext.Class类的实例。

依据我们上面讲的,Ext.Class类是一个工厂函数。这就是说,我们创建的新类,它不是继承于Ext.Class. 之前我们讲过,所有的类都是继承于Ext.Base. 所以,我们在使用Ext.create方法时,Ext在幕后运行了很多的处理过程。每一个处理过程在创建一个类时都有特定的目的。

一个处理过程可以为异步,也可以为同步,比如,有一个处理过程,运行到它时,用来加载我们创建的新类所需要的所有依赖(依赖还没有被加载时)。当这个过程运行完后,下一个处理过程会被执行,直到整个任务链表为空,然后一个新的类被创建。

一个preprocessor是在创建Ext.Class实例之前运行的过程。换句话说,就是在创建一个新类之前运行的过程。它所对应的每一个过程,都能改变我们类的行为。

一个postprocessor是在我们创建完一个类之后运行。比如创建一个类的单例,或者给我们的定义一个别名,等等。

在Ext库中,已经定义了很多的处理过程,但我们也可以定义过程,并且添加到处理队列中。

现在的问题是,这里有哪此过程?它们是用来做什么的。我们可以通过以下的几行代码,打印所有的预处理和后处理过程.

var pre = Ext.Class.getDefaultPreprocessors();
var post = Ext.ClassManager.defaultPostProcessors();
console.log(pre);
console.log(post);

Output:

["className", "loader", "extend", "privates", "statics",
"inheritableStatics", "platformConfig", "config", "cachedConfig",
"mixins", "alias"]
["alias", "singleton", "alternateClassName", "debugHooks",
"deprecated", "uses"]

下面的图片表示了整个的处理流程

这里写图片描述

上图显示在创建一个类时的所有经过。所有的preprocessors都在创建类之前运行,修改最终创建的类。而postprocessors则在类已经准备被使用时运行。

举例来说,loader 过程主要是用来处理依赖,如果需要的依赖还没存在,则它以同步的方法(阻此之后的代码执行)加载依赖的js文件。在所有的依赖准备好之后,才把控制权传递给Ext.Class,让它继承执行接下来的处理程序。接下来的处理过程是extend, 它主要负责将superclass(加载过的依赖文件, 父类)中原型方法和属性复制给要创建的子类。

以下这个表格简单的描述了各预处理过程。

PreprocessorsDescription
className根据define方法中的字符串,定义类的空间和名字
loader用来查找依赖,如果依赖不存在,则尝试加载它们
extend从加载的父类中,继承原型中的方法和属性
statics为创建的当前类,定义静态的方法和属性
inheritableStatics如果可以,从父类中复制static方法
config为可配置的属性创建getter和setter方法
mixins从mixins属性中指定的类,继承这些类中指定的方法和属性
alias为这个新创建的类设置一个别名

一旦一个类创建完成,以下的postprocessors将会被执行

PostprocessorDescription
alias在class manager中注册一个新的类,以及这个类的别名
singleton如果在define方法中指定了singleton属性,则以单例的模式,创建这个类的实例
alertnateClassName修改新创建类的别字
uses导入将被使用的类,以及新创建的类

上面的过程,有的不会被运行,这取决于在定义类时define()方法中的配置。

现在你对如何创建一个类系统有一个基本的认识,我们将继承使用这此处理流程定义我们的类以及使用它们。

Mixing many classes

目前为此,我们只学习了简单的继承,但我们也可以使用mixins处理流程,模似多重继承。它的概念非常简单:我们可以将多个类,混合到一个类。最后,新的类可以从所有的被混合的类访问它们的属性和方法。

一个公司中的职业变化依赖于组织关系,一个秘书(Secretary)根据她所负责的经理或会计师,执行不同的职责。所要我们需要将每个职业的职责独立出来。以下是它们的关系图

这里写图片描述

//将每个职责,定义成类
Ext.define('Myapp.sample.tasks.attendPhone',{
    answerPhone:function(){
    console.log( this.name + ' is answering the phone');
    }
});

Ext.define('Myapp.sample.tasks.attendClient',{
    attendClient:function(clientName){
        console.log( this.name + ' is attending client: ' + clientName);
    }
});
Ext.define('Myapp.sample.tasks.attendMeeting',{
attendMeeting:function(person){
console.log( this.name + ' is attending a meeting with ' +
person);
}
});
Ext.define('Myapp.sample.tasks.superviseEmployees',{
    superviseEmployee:function(supervisor, employee){
        console.log( supervisor.name + ' is supervising : ' +
        employee.name + ' ' + employee.lastName);
    }
});

以下,我们定义每个职业类

//基础类
Ext.define('Myapp.sample.Employee',{
    name: 'Unknown',
    lastName: 'Unknown',
    age: 0,
    constructor: function (config){
        Ext.apply( this, config || {} );
        console.log('class created – fullname:' + this.name + ' ' +
        this.lastName);
    },
    checkAge:function(){
        console.log( 'Age of ' + this.name + ' ' + this.lastName + ' is:'
        + this.age );
    },
    work: function( task ){
        console.log( this.name + ' is working on: ' + task);
    }
});
//秘书类
Ext.define('Myapp.sample.Secretary',{
    extend:'Myapp.sample.Employee',
    mixins:{
        answerPhone: 'Myapp.sample.tasks.attendPhone'
    },
    constructor: function (config){
        Ext.apply(this, config || {});
        console.log('Secretary class created – fullname:' + this.name
        + ' ' + this.lastName);
    }
});
//会计类
Ext.define('Myapp.sample.Accountant',{
    extend:'Myapp.sample.Employee',
    mixins:{
        attendClient: 'Myapp.sample.tasks.attendClient',
        attendMeeting: 'Myapp.sample.tasks.attendMeeting'
    },
    constructor: function (config){
        Ext.apply(this, config || {});
        console.log('Accountant class created – fullname:' + this.name
        + ' ' + this.lastName);
    }
}); 

Ext.define('Myapp.sample.Manager',{
    extend:'Myapp.sample.Employee',
    mixins:{
        attendClient: 'Myapp.sample.tasks.attendClient',
        attendMeeting: 'Myapp.sample.tasks.attendMeeting',
        supervisePersons:'Myapp.sample.tasks.superviseEmployees'
    },
    constructor: function (config){
        Ext.apply(this, config || {});//this.name= config.name;
        console.log('Manager class created – fullname:' + this.name +
        ' ' + this.lastName);
    },
    supervise: function(employee){
        console.log( this.name + ' starts supervision ');
        this.mixins.supervisePersons.superviseEmployee(this,
        employee);
        console.log( this.name + ' finished supervision ');
    }
}); 

在这里,我们创建了三个类(Secretary, Account, and Manager). 每个类都继承于Employee, 每一个类都是继承于Employee类,并且通过mixins继承其它的类方法。以下是这个类的使用

// Usage of each class
var patricia = Ext.create('Myapp.sample.Secretary', {
    name:'Patricia', lastName:'Diaz', age:21 } );
patricia.work('Attending phone calls');
patricia.answerPhone();
var peter = Ext.create('Myapp.sample.Accountant', {name:'Peter',
    lastName:'Jones', age:44 } );
peter.work('Checking financial books');
peter.attendClient('ACME Corp.');
peter.attendMeeting('Patricia');
var robert = Ext.create('Myapp.sample.Manager', {name:'Robert',
    lastName:'Smith', age:34 } );
robert.work('Administration of the office');
robert.attendClient('Iron Tubes of America');
robert.attendMeeting('Patricia & Peter');
robert.supervise(patricia);
robert.supervise(peter);

这里写图片描述

使用mixinConfig属性

使用mixinConfig属性,使得被混入的类,可以提供before和after勾子函数,而这些可以不用在新类中定义(即,可以为新类中的方法, 提供这个方法执行和执行后的函数)。

简单的理解就是,在mixinConfig中的before和after中定义的方法,可以在这个对应的方法调用时执行。所以mixinConfig中的设置相当于一个监听器(观察者), 当一个附加的函数被调用时,将执行这个方法所对应的before和after对应的方法。

//定义一个监听器,或者将被混入的类
Ext.define('Myapp.sample.tasks.attendCellPhone',{
    extend: 'Ext.Mixin',
    /* answerCellPhone是一个监听的函数,当这个函数执行时
    分别调用对应的cellPhoneRinging和finishCall
    */
    mixinConfig:{
    before:{
    answerCellPhone:'cellPhoneRinging'
    },
    after:{
    answerCellPhone:'finishCall'
    }
    },
    cellPhoneRinging: function(){
    console.log( 'cell phone is ringing you may attend call');
    },
    finishCall: function(){
        console.log( 'cell phone call is over');
    }
});

以下的代码混合上面的类

Ext.define('Myapp.sample.Secretary',{
    extend:'Myapp.sample.Employee',
    mixins:{
        answerPhone: 'Myapp.sample.tasks.attendPhone',
        util:'Myapp.sample.tasks.attendCellPhone'
    },
    constructor: function (config){
        Ext.apply(this, config || {});//this.name= config.name;
        console.log('Secretary class created – fullname:' + this.name
        + ' ' + this.lastName);
    },
    answerCellPhone:function(){
        console.log( this.name + ' is answering the cellphone');
    }
});

这里写图片描述

在Ext库中,Ext.util.Observable, Ext.util.Floating, Ext.state.Stateful都可以被认为是mixins, 每一个类都只负责特定的事情。在一个大型的应用编码前,我们最好对应用程序的结构进行组织。

Singleton Class

一个singleton class 只能实例化一次。Ext允许我们通过一个postprocessor(过程),就能非常简单的创建一个singleton class.

如果我们想要一个类为singleton, 我们只需要指定singleton属性为true. 它就可以打开相应的后处理过程(postprocessor).

Ext.define('Myapp.CompanyConstants',{
    singleton: true,
    companyName: 'Extjs code developers Corp.',
    workingDays: 'Monday to Friday',
    website: 'www.extjscodedevelopers.com',
    welcomeEmployee: function (employee){
        "Hello " + employee.getName() + ", you are now working for " +
        this.companyName;
    }
});

以上这个类,在我们的应用程序中,将只有一个实例。 我们不在需要使用 Ext.create创建这个类的实例,我们可以通过以下方式调用

alert( Myapp.CompanyConstants.companyName );
var patricia = Ext.create('Myapp.sample.Employee', {
    name:'Patricia',
    lastName:'Diaz',
    age:21,
    isOld:false
});
console.log(Myapp.CompanyConstants.welcomeEmployee(patricia));

Aliases

一个alias是一个类的简短名称, Ext.ClassManagers 将后为实际的类,添加一个别名。通常,一个别名为都为小写

这个特性在使用xtype创建widgets时非常有用。比如

Ext.define('Myapp.sample.EmployeePanel',{
    extend: 'Ext.panel.Panel',
    alias: 'widget.employeePanel',
    alternateClassName: 'mycustomemployeepanel',
    title: 'Employee Panel',
    html: 'Employee content here..!'
});

在上面的代码中,我们通过alias创建了一个简短名称。我们也使用了widget作为前缀,表明,我们正在创建一个组件。一个组件的类可以为window, grid, or panel.

当然,在这个类中,我们也定义了alternateClassName属性,它让我们为新的类定义了一个别名。这个属性可以是一个字符串,或者是一个数组对像(多个别名), [‘employeepanel’,’customEmployeePanel’, ‘employeeboard’].

在Ext JS中,使用以下的别名,表示对应的空间

  • feature: This is used for Grid features
  • plugin: This is used for plugins
  • store: This is used for Ext.data.Store
  • widget: This is used for components

现在,让我们使用alias 创建一个类

Ext.onReady (function(){
    Ext.create('widget.employeePanel',{
        title: 'Employee Panel: Patricia Diaz...',
        height:250,
        width:450,
        renderTo: Ext.getBody()
    });
});

也可以使用alternateClassName:

Ext.onReady (function(){
    Ext.widget('employeePanel',{
        //using the xtype which is employeePanel
        title: 'Employee Panel: Patricia Diaz...',
        height:250,
        width:450,
        renderTo: Ext.getBody()
    });
});

让我们解释下整个过程,我们先定义了一个Myapp.sample.EmployeePanel,它继承了Ext.panel.Panel. 因此这个类是一个widget, 所以我们习惯性的给它的alias命名为widget.employeePanel. 如我们之前所说的, Ext.ClassManager会处理我们新创建这个类的声明(在内部,使用preprocessors和postprocessors) ,为之后的使用将定义/映射这个alias name. 所以,当我们创建一个Myapp.sample.EmployeePanel的实例时, Ext JS 将知如何处理和执行代码。

另外,我们也可以使用其它的方法引用这个新的类

Ext.ClassManager.instantiateByAlias("widget.employeePanel",{
renderTo: Ext.getBody()
});
// OR
Ext.createByAlias("widget.employeePanel",{
renderTo: Ext.getBody()
});

Ext.createByAlias只是Ext.ClassManager.instantiateByAlias的一个快捷方式。同样,我们也可以使用xtype来引用一个新类

var win = Ext.create("Ext.window.Window",{
    title: "Window", width:350, height:250,
    items: [{ xtype: "employeePanel" }]
});
win.show();

按需加载类

当我们开发一个大型的应用时,性能是非常重要的。我们只需要加载我们所需要的;这意味着,如果我们的应用程序有很多的模块,我们应当将它们独立出来到各个包中,然后单独加载。

从 Ext JS 4开始, 我们可以按需要,动态加载类和文件。所以我们可以在每个类中配置依赖,然后Ext 库后加载它们.

你需要知道使用loader对于开发模式非常有用,因为loader把一个一个的包含所有类,这使得我们可以调试代码。可是,不推荐在产品环境中加载所有的类。而应该创建这些类的包,然后按需要加载它们
* 一个文件只定义一个类
* 类的名称应当跟Javascript的文件名称一致
* 类的空间名称应该跟文件夹的结构匹配。比如,如果我们定义了一个MyApp.customers.controller.Main, 我们应该在MyApp/customers/controller下创建一个Main.js文件

允许加载器

loader 系统的enabled or disabled依赖于我们在html中引入的Ext文件。如果我们导入的是extjs/build文件夹下的ext-all or ext-all-debug文件, loader会被禁止使用,因为所有的Ext库已经被加载了。如果是extjs目录下的ext-all 或者ext-all-debug文件,则loader是enabled, 因为这此只有核心类被加载。

如果我们需要使用loader有效, 我们应该在JS文件的开头,写入如下的代码

Ext.Loader.setConfig({
    enabled: true
});

上面的代码,允许我们按需要加载类。即在创建一个类时,有一个preprocessor用来加载还不存在的类。

为了开始加载类,我们需要设置这个类所有的路径。我们可以有两种方法,我们可以使用Loader的setConfig方法,并定义paths属性,如下所示

Ext.Loader.setConfig({
    enabled:true,
    paths:{
        MyApp:'appcode'
    }
});

paths属性接受一个对像,它包含了我们应用程序的root namespace 和在这个命名空间下,所有类所在的目录。所以在上面的代码中,当我们引用Myapp, Ext JS将会查找appcode/ 文件夹。我们也可以在这里添加许多其它的路径。

一旦我们正确配置了loader, 我们可以使用require加载我们的类

Ext.require([
    'MyApp.Constants',
    'MyApp.samples.demoClass'
]);

require会为我们创建一个script tag. 在所有的文件加载完成后,onReady事件会被触发。然后在onReady的回调函数中,我们可以使用所有加载完的类。

如果我们在require调用之后, 直接使用这些类,我们会获得一个error, 这是因为类还在下载和创建,它们还不存在。这也是为什么我们需要使用onReady,它会等待所有的都加载完成后使用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值