02_核心概念--01_类体系

综述

Ext JS拥有大量的类。到目前为止,我们有超过200万的开发人员,他们有不同的背景,来自不同的地方。面对这么大规模的开发人员,我们想要提供一个如下特点的通用代码框架,变得有些困难:

*简单易学

*快速开发,容易调试,轻松部署。

*结构化,可扩展,可维护。

因为JavaScript是一个无类的,面向原型(参见:https://en.wikipedia.org/wiki/Prototype-based_programming)的语言,所以它最强大的特点之一是灵活性。通过使用很多种编程风格和技术,我们能够为任何问题提供多种解决方案。然而,代价是,这些解决方案是不确定的。没有一个统一的结构,JavaScript代码将变得很难理解,维护和重用。

从另一方面来说,基于类的编程(参见:https://en.wikipedia.org/wiki/Class-based_programming)仍是最流行的面向对象编程的编程模式。基于类的编程语言通常需要强类型,封装和标准的编码约定。通过让开发人员遵循大量的规则,经过一段时间后,代码似乎会可维护,可扩展,可计量。然而这种模式没有JS开发的动态特性。

每种方法都有好跟坏的一面,但我们能否保持两种模式下好的方面,而去掉坏的方面呢?答案是肯定的,你将在Ext JS里找到解决方案。

命名约定

坚持使用基于类,命名空间和文件名的命名约定,可以让你的代码更有组织性,结构化和可读性。

类名或许只包含数字跟字母。数字被允许但不被鼓励使用,除非它们属于专业技术术语。不要使用下划线,连字号,或其它非数字与字母的字符。例如:

MyCompany.useful_util.Debug_Toolbar isdiscouraged

MyCompany.util.Base64 is best

类名应该被划分到合适的组,这些组使用类似对象属性的点记法(即.)来命名。在类名前,至少要有一个顶级的命名空间。例如:

MyCompany.data.CoolProxy

MyCompany.Application

顶级的命名空间和实际的类名应该使用大骆驼拼写法。其它的使用小写字母。例如:

MyCompany.form.action.AutoLoad

非Sencha发布的类不能使用Ext作为顶级命名空间。

首字母缩写词也应该遵循上面列出的大骆驼拼写法。例如:

Ext.data.JsonProxy instead ofExt.data.JSONProxy

MyCompany.util.HtmlParser instead ofMyCompary.parser.HTMLParser

MyCompany.server.Http instead ofMyCompany.server.HTTP

源码文件

类的命名直接与源码文件存放路径相匹配。这样一来,每个类需要单独存放成一个文件。例如:

Ext.util.Observable 的存放路径为:path/to/src/Ext/util/Observable.js

Ext.form.action.Submit存放在: path/to/src/Ext/form/action/Submit.js

MyCompany.chart.axis.Numeric存放于: path/to/src/MyCompany/chart/axis/Numeric.js

path/to/src是你程序的类文件存放的路径。为了得到最好的开发,维护与部署体验,所有的类都应该被存放在这个通用的根目录下,并且被分组到合适的命名空间。

方法和变量

与类的命名方式类似,方法与变量的名称也只能包含数字或字母型字符。数字被允许但不被鼓励使用,除非它们属于专业技术术语。不要使用下划线,连字号,或其它非数字与字母的字符。

方法与变量名应该总是使用小骆驼拼写法。这同样应用于首字母缩写词。

示例

合法的方法名:

encodeUsingMd5()

getHtml() instead of getHTML()

getJsonResponse() instead ofgetJSONResponse()

parseXmlContent() instead ofparseXMLContent()

合法的变量名:

var isGoodName

var base64Encoder

var xmlReader

var httpServer

属性

属性命名遵循两样的命名规范,除非它们是静态常量。

静态类中的静态常量属性应该所有字母大写。例如:

Ext.MessageBox.YES = "Yes"

Ext.MessageBox.NO = "No"

MyCompany.alien.Math.PI = "4.13"

 

声明

你可以仅调用一个方法就可以创建类:Ext.define。它的基本语法如下:

Ext.define(className, members,onClassCreated);

className:类名

members是一个的对象,该对象由键值对集合组成类成员。

onClassCreated是一个可选的回调函数。当定义的类的所有依赖准备好,并且该类本身已经完全被创建,这个函数就会被调用。由于类创建是异步的,这个回调函数在很多情况下非常有用。这些将在本章节第四部分讨论。

示例:

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");

注释:我们使用Ext.create()方法创建了一个My.sample.Person类的新实例。我们也可以使用new关键字(new My.sample.Person())。然而,我们还是推荐养成使用Ext.create()的使用习惯,因为它能让你有动态加载的优点。

更多关于动态加载的信息,请参看入门指南章节(http://docs.sencha.com/extjs/6.2.1/guides/getting_started/getting_started.html)。

 

配置

还有一个专用的config属性,它会在类创建之前被强大的Ext.class预处理器处理。它有如下特点:

* 配置项与其它类成员相比,是完全密封的。

* 如果每个配置属性的Getter与Setter方法没有定义,它们会在类的创建过程中在类的原型中自动生成。

* 自动生成的setter方法在设置值之前会调用apply方法(如果它在类中被定义)。如果你想在设置值之前需要运行自定义的逻辑代码,你可以为一个配置属性项重写并覆盖apply方法。如果你的apply方法没有返回值,setter方法将不会成功设置值。当不同的值被设置时,update方法(如果定义了的话)也会被调用。apply和update方法都会传入两个参数,一个是新值,一个是旧值。

使用configs属性的Ext类,你不需要手动调用initConfig()方法。然而 ,如果你的类是继承自Ext.Base,initConfig()方法仍然需要调用。

请看如下的配置示例。

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) {
               return Ext.create('My.own.WindowBottomBar', bottomBar);
           }
           else {
               this.bottomBar.setConfig(bottomBar);
           }
       }
   }
});

如下是它的使用示例:

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

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配置项来定义

Ext.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"
/** A child component to complete the example. */
Ext.define('My.own.WindowBottomBar', {
   config: {
       height: undefined,
       resizable: true
   }
});

错误处理和调试

Ext JS有很多有用的特性可以帮助你调试和进行错误处理。

* 你可以使用Ext.getDisplayName()来得到任何方法的显示名称。在有类名和方法名声明的类中,对处理抛出异常错误特别有用。

 throw new Error('['+ Ext.getDisplayName(arguments.callee)+'] Some message here');

 

* 在任何使用Ext.define()定义的类的方法中,当一个错误被抛出时,如果你使用的浏览器是基本WebKit的(Chrome或者Safari),你可以在调用堆栈中看到类名和方法名。例如,如下是在Chrome浏览器中看到的样子:

 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值