专栏首页LeoXu的博客[翻译]Ext JS 教程-类系统 原

[翻译]Ext JS 教程-类系统 原

<h3>类系统</h3> <p>ExtJS 史上第一次进行了重整新的类系统的大重构。新的架构以ExtJS 4.X所编写的每一个类作为后盾,因此在你编写代码以前理解它是非常重要的。</p> <p>这个手册主要面向任何想在ExtJS 4.x中新建或者扩展类的开发人员。它分成四个部分:</p> <p>Ø 部分一:“综观”解释了稳定的类系统的需求</p> <p>Ø 部分二:“命名规则”讨论给类、方法、属性、变量和文件命名的最佳实践</p> <p>Ø 部分三:“动手实践”提供详细的一步步编码的例子</p> <p>Ø 部分四:“错误处理&amp;调试”提供如何处理一场的小建议和小计谋</p> <h3>一 综观</h3> <p>ExtJS 4 靠超过300 多个类驱动。我们拥有一个超过20万来自世界各地,具备各种编程背景的开发人员组成的巨大社区。在一个框架的范围内,我们面对提供一个通用的编码结构的那些大挑战:</p> <p>Ø 简单易上手</p> <p>Ø 开发快速、调试简单、部署无忧</p> <p>Ø 结构良好,可扩展可维护</p> <p>JavaScript 是 classless 的面向原型的语言。天性使然,灵活是这个语言最强大的特性。使用不同的方式,不同的编码形式和技术,都可以让工作有效。然而就是那个特性,带来了不可预知的代价。没有一个统一的形式,JavaScript代码可能很难去理解、维护和重用。</p> <p>从另一方面来看,基于类的编程仍然是面向对象编程领域最受欢迎的模式。基于类的语言常常需要强类型,提供封装和标准的编码规范。一般而言要让开发人员遵守一大堆规则,而编码就会变得一直可预知、可扩展和规规矩矩。然而,他们不会有在JavaScript这样的语言中发现的同样的动态能力。</p> <p>每种方法都有其利弊,但是我们是否可以利用两者好处的同时避免他们的坏处呢?答案是肯定的,我们在ExtJS 4中实现了这个解决方案。</p> <h4>二 命名规范</h4> <p>至始至终为你编码的类、命名空间和文件名使用一致的命名规则有助于保持你代码的组织性、结构性和可读性。</p> <h4>1)类</h4> <p>类名应该只包含字母和数字字符。数字在大多数情况下是不鼓励使用的,除非他们属于一种技术手段。不要使用下划线,连字符或者其它任何非字母非数字的字符。举个例子:</p> <p>Ø MyCompany.useful_util.Debug_Toolbar 不鼓励这样命名</p> <p>Ø MyCompany.util.Base64 是可以被接受的</p> <p>类名应该被组成成为包,在包中合适恰当的使用对象属性点记号(.)分出命名空间。至少,应该只有唯一的顶层命名空间后面跟类名。举个例子:</p> <p>MyCompany.data.CoolProxy</p> <p>MyCompany.Application</p> <p>顶层命名空间和真实类的命名应该采用Camel形式(单词的首字母都大写),其它所有事物都应该是小写的。举个例子:</p> <p>MyCompany.form.action.AutoLoad</p> <p>不是Sencha发行的类永远不应该使用Ext作为顶层命名空间的名字。</p> <p>首字母缩略词也应该遵守上面列出的Camel形似命名规则。示例如下:</p> <p>Ext.data.JsonProxy 而不是Ext.data.JSONProxy</p> <p>MyCompany.util.HtmlParser 而不是 MyCompary.parser.HTMLParser</p> <p>MyCompany.server.Http 而不是MyCompany.server.HTTP</p> <h4>2)源代码</h4> <p>类地址的名字应该直接指向文件被存储的路径。基于此,每个文件中只能有一个类,示例如下:</p> <p>Ext.util.Observable 被存储在路径 /to/src/Ext/util/Observable.js 中</p> <p>Ext.form.action.Submit 被存储在路径 /to/src/Ext/form/action/Submit.js中</p> <p>MyCompany.chart.axis.Numeric 被存储在路径 /to/src/MyCompany/chart/axis/Numeric.js中</p> <p>Path/to/src 是你的应用程序类所在的路径。所有的类都应该在这个公共的根下面,并且为了获得最好的开发、维护和部署体验,适当的赋予命名空间。</p> <p>2)方法和变量</p> <p>跟类名类似,方法和变量的名字应该只包含数字和字母字符。数字被允许的,但在大多数情况下是不被鼓励的,除非是属于某种技术手段。不要使用下划线、连字符,或者任何其它非字母和数字的字符。</p> <p>方法和变量名字应该一直使用camel形式(第一个单词首字母小写,接下来的单词首字母都大写)。这也同样适用于首字母缩略词。</p> <p>示例:</p> <p>可以被接受的方法名字:encodeUsingMd5() getHtml() instead of getHTML() getJsonResponse() 而不是:getJSONResponse() parseXmlContent() instead ofparseXMLContent()</p> <p>可以被接受的变量名称: var isGoodName var base64Encoder var xmlReader var httpServer</p> <h5>3)属性</h5> <p>类属性的命名规则同上述方法和变量的命名规则是完全一样的,除开它们是静态常量的情况。</p> <p>静态常量类属性应该都是大写的。示例如下:</p> <p>Ext.MessageBox.YES = &quot;Yes&quot;</p> <p>Ext.MessageBox.NO = &quot;No&quot;</p> <p>MyCompany.alien.Math.PI = &quot;4.13&quot;</p> <h4>三 动手实践</h4> <h5>1. 声明</h5> <p><b>1.1</b><b>)老方法</b></p> <p>如果你使用过任何ExtJS的老版本,你一定熟悉使用 Ext.extend 去创建一个类:</p> <p>var MyWindow = Ext.extend(Object, { ... });</p> <p>这种方法很容易用来去创建一个继承另外一个类的新类。然而不像其它方式的继承,我们没有流畅的创建类的其它方面的API,比如配置,静态性和混合。我们很快将会重新详细的了解这些东西。</p> <p>让我们看一下另外一个例子:</p> <p>My.cool.Window = Ext.extend(Ext.Window, { ... });</p> <p>在这个例子中我们给新类带上了命名空间,并且让它继承了 Ext.Window。这里我们需要专注于两个概念:</p> <p>1. My.cool 需要在我们把 Window 当作它的属性前,是一个存在的对象</p> <p>2. Ext.Window 在它能被引用前需要存在或者已经被加载进来</p> <p>第一条常常使用 Ext.namespace(用 Ext.ns作别名)来解决。 这个方法横向递归对象/属性树,并在他们还不存在时创建之。 烦人的地方在于,你需要一直牢记把它们加在 Ext.extend 之上。</p> <p>Ext.ns('My.cool');</p> <p>My.cool.Window = Ext.extend(Ext.Window, { ... });</p> <p>第二条专注起来不是很容易,因为 Ext.window 也许依赖于其它直接或间接继承的类,并且这样轮转下去,这些依赖也依赖于其它类的存在。由于那个原因,编写应用程序之前ExtJS 4 常常要包含包括了整个库的 ext-all.js ,即使他们也许仅仅只需要这个框架的一小部分。</p> <p><b>1.2</b><b>)新方法</b></p> <p>ExtJS 4 仅仅使用一个方法排除了所有那些缺点。你仅需要记住如何创建类: Ext.define。它的简单语法是像下面这样:</p> <p>Ext.define(className, members, onClassCreated);</p> <p>className:类的名字</p> <p>Members 代表一个类成员的键值对集合的对象</p> <p>onClassCreated 是一个在类的所有依赖都已经准备好时回掉执行的可选方法,同时这个类本身完全创建了。归功于新的创建类的异步形式,这种会掉在很多情况下都会很有用。这将在第四部分讨论到。</p> <p>示例:</p> <p>Ext.define('My.sample.Person', {</p> <p>name: 'Unknown',</p> <p>constructor: function(name) {</p> <p>if (name) {</p> <p>this.name = name;</p> <p>}</p> <p>},</p> <p>eat: function(foodType) {</p> <p>alert(this.name + &quot; is eating: &quot; + foodType);</p> <p>}</p> <p>});</p> <p>var aaron = Ext.create('My.sample.Person', 'Aaron');</p> <p>aaron.eat(&quot;Salad&quot;); // alert(&quot;Aaron is eating: Salad&quot;);</p> <p>注意我们用 Ext.create() 方法创建了一个 My.sample.Person 的新实体。我们可能使用新的关键字(My.name.Person())。然而建议你形成一直使用 Ext.create 的习惯,因为它允许你利用动态加载的好处。更多关于动态加载的内容见入门指南。</p> <h5>2. 配置</h5> <p>在 ExtJS 4种,我们推出专注的 config 属性,它在类被创建以前通过强大的 Ext.Class 前处理器获得处理。特性包括:</p> <p>对于其它类成员来说配置是完全封装的。</p> <p>每一个配置属性的获取和设置方法将在类创建期间自动生成到类的原型中,如果这些方法还没有被定义。</p> <p>一个apply方法也为每一个配置属性生成了。自动生成的设置器方法在设置值之前内部调用apply方法。如果你需要在设值之前运行一些定制逻辑,重写config属性的apply方法,如果apply没有返回值,那么设置器将不会设值。示例见下面的 applyTitle.</p> <p>这是一个示例:</p> <p>Ext.define('My.own.Window', {</p> <p>/** @readonly */</p> <p>isWindow: true,</p> <p>config: {</p> <p>title: 'Title Here',</p> <p>bottomBar: {</p> <p>height: 50,</p> <p>resizable: false</p> <p>}</p> <p>},</p> <p>constructor: function(config) {</p> <p>this.initConfig(config);</p> <p>},</p> <p>applyTitle: function(title) {</p> <p>if (!Ext.isString(title) || title.length === 0) {</p> <p>alert('Error: Title must be a valid non-empty string');</p> <p>}</p> <p>else {</p> <p>return title;</p> <p>}</p> <p>},</p> <p>applyBottomBar: function(bottomBar) {</p> <p>if (bottomBar) {</p> <p>if (!this.bottomBar) {</p> <p>return Ext.create('My.own.WindowBottomBar', bottomBar);</p> <p>}</p> <p>else {</p> <p>this.bottomBar.setConfig(bottomBar);</p> <p>}</p> <p>}</p> <p>}</p> <p>});</p> <p>/** A child component to complete the example. */</p> <p>Ext.define('My.own.WindowBottomBar', {</p> <p>config: {</p> <p>height: undefined,</p> <p>resizable: true</p> <p>}</p> <p>});</p> <p>而下面是一个它是如何被使用的例子:</p> <p>var myWindow = Ext.create('My.own.Window', {</p> <p>title: 'Hello World',</p> <p>bottomBar: {</p> <p>height: 60</p> <p>}</p> <p>});</p> <p>alert(myWindow.getTitle()); // alerts &quot;Hello World&quot;</p> <p>myWindow.setTitle('Something New');</p> <p>alert(myWindow.getTitle()); // alerts &quot;Something New&quot;</p> <p>myWindow.setTitle(null); // alerts &quot;Error: Title must be a valid non-empty string&quot;</p> <p>myWindow.setBottomBar({ height: 100 });</p> <p>alert(myWindow.getBottomBar().getHeight()); // alerts 100</p> <h5>3. 静态成员</h5> <p>静态成员可以使用 statics 配置被定义。</p> <p>Ext.define('Computer', {</p> <p>statics: {</p> <p>instanceCount: 0,</p> <p>factory: function(brand) {</p> <p>// 'this' in static methods refer to the class itself</p> <p>return new this({brand: brand});</p> <p>}</p> <p>},</p> <p>config: {</p> <p>brand: null</p> <p>},</p> <p>constructor: function(config) {</p> <p>this.initConfig(config);</p> <p>// the 'self' property of an instance refers to its class</p> <p>this.self.instanceCount ++;</p> <p>}</p> <p>});</p> <p>var dellComputer = Computer.factory('Dell');</p> <p>var appleComputer = Computer.factory('Mac');</p> <p>alert(appleComputer.getBrand()); // using the auto-generated getter to get the value of a config property. Alerts &quot;Mac&quot;</p> <p>alert(Computer.instanceCount); // Alerts &quot;2&quot;</p> <h4>四 错误处理和调试</h4> <p>ExtJS 4 包含一些能在调试和错误处理工作上帮助你的有用特性。</p> <p>你可以使用 Ext.getDisplayName() 去得到任何方法名字的显示。这在抛出错误时在错误描述信息中显示类名和方法名,特别有用。</p> <p>throw new Error('['+ Ext.getDisplayName(arguments.callee) +'] Some message here');</p> <p>如果一个错误在任何使用 Ext.define() 定义的类的任何方法中被抛出, 你应该使用一个基于 Webkit 内核的浏览器(Chrome 或者 Safari)去观察调用堆栈中方法和类的名字。例如,下面是它如何在Chrome中显示:</p> <p><a href="http://static.oschina.net/uploads/img/201305/30194951_odHt.jpg"><img title="clip_image002" style="border-top: 0px; border-right: 0px; background-image: none; border-bottom: 0px; padding-top: 0px; padding-left: 0px; border-left: 0px; display: inline; padding-right: 0px" border="0" alt="clip_image002" src="http://static.oschina.net/uploads/img/201305/30194954_EM97.jpg" width="740" height="520" /></a></p> <h4>还要看看</h4> <p>· <u><a href="http://www.sencha.com/blog/countdown-to-ext-js-4-dynamic-loading-and-new-class-system">Dynamic Loading and the New Class System</a></u></p> <p>· <u><a href="http://edspencer.net/2011/01/classes-in-ext-js-4-under-the-hood.html">Classes in Ext JS 4: Under the Hood</a></u></p> <p>· <u><a href="http://edspencer.net/2011/01/ext-js-4-the-class-definition-pipeline.html">The Class Definition Pipeline</a></u></p>

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • [翻译]Ext JS 教程-MVC架构 原

    大规模的客户端应用程序常常难于去编写、组织机构和维护。随着你加入更多的功能,并且投入更多的开发人员,它们渐渐趋向于失去控制。ExtJS 4 带来了一种新的不仅...

    LeoXu
  • [翻译]Ext JS 教程-ExtJS 4中的数据包(Package)

    数据包(data package)是用来加载和保存你应用程序中的数据的东西,包含41个类,但是其中有三个类比所有其他类更加重要——Model,Store和Ext...

    LeoXu
  • [翻译]Ext JS 教程-组件 原

    一个ExtJS 应用程序是由一个或者更多个叫做组件的窗口小部件组成的。所有的组件都是Ext.Component类的子类,它允许它们参与到自动的生命周期管理中去...

    LeoXu
  • ExtJS中xtype一览

    基本组件: xtype Class 描述 button Ext.Button 按钮 splitbutton Ext.SplitButton 带...

    hbbliyong
  • Ext整体印象

    其实国内不乏有自己开发自己框架的公司,比如上海的道锐(不如Ext全面,更侧重于其业务经验)等,一直以来我们关心的重点都在服务器端(如程序结构、设计模式、数据库设...

    用户1183026
  • 阅读Ext 学习Javascript(一)Core/Ext.js

    从Library的角度去看,Ext(喜欢中文的朋友可以到它的中文站看看)和Prototype JQuery YUI没有太大区别,但它有它的优点,完整的OO支持、...

    用户1183026
  • 对于Ext.data.Store 介紹 与总结,以及对以前代码的重构与优化

         对于Ext.data.Store 一直不是很了解,不知道他到底是干嘛的有哪些用处,在实际开发中也由于不了解也走了不少弯路, store是一个为Ext器...

    hbbliyong
  • EXTJS7 eventedConfig用法

    路过君
  • 如何能轻松做好仓库管理工作

    一:首先仓库的规划要合理仓库划分为几个区,每个区的主要重点在什么地方,每个区是以货架为主还是以托盘为主,还是以定置线为主,要有所规划。货架区,有几个货架,每个货...

    明象ERP
  • Excel实战技巧66:创建向导样式的数据输入窗体5

    到目前为止,我们已经完成了最艰难的工作。接下来,我们来编写用户窗体代码,将已完成的对象放进HRWizard用户窗体里并使这些对象工作。

    fanjy

扫码关注云+社区

领取腾讯云代金券