如何架构EXTJS项目

来源:互联网 发布:mastercam9.1车床编程 编辑:程序博客网 时间:2024/05/10 14:40
  

翻译了下面这篇文章,感觉老外说话真是够啰嗦详细。很多地方我都只是意译了事。

这篇文章其实是说了如何架构Ext项目。印象比较深刻的是Pre-configured classes(预配置类),因为目前我还都只是直接使用Ext的组件。

原文在这里http://extjs.com/learn/Tutorial:Writing_a_Big_Application_in_Ext

指南: 用Ext开发大型应用

序言

这篇文章,是给那些不再在一个HTML页面里面只是嵌入一个简单的Window或form的Ext 2.x用户,是给那些已经决定了以Ext为未来之路的开发者,以及那些感到自己的应用需要一个结构并正在到处辛苦地搜寻相关文章的人们。

问题产出的原因,和解决这些问题的方式,它们的数量等于面对着这些问题的人数。我下面描述的并不是唯一的解决方式,而我也没说其它方式就是不好。

我想说的是我这个方法是可行的,结构优美的,容易维护的。

什么是“大型应用”?

如果你只有一个Viewport,里面嵌着一个BorderLayout, grid和form,所有这些都在一个文件里面,它是不是大型应用?如果你有数十个装着grid、form或者border layout的window,分别保存在数十个文件中,这才叫做大型应用,是这样吗?

上述两种情况都不能用肯定和否定来回答。什么时候应用才算是大?答案很简单:当你感觉到它“大”的时候;当你面对一堆文件,或想在某个文件里面寻找某些代码片段遇到麻烦的时候;当你难以理解组件间的关系的时候,等等。

我们应该把每个应用都看待成大型应用,把代码写好,为它真正变成大型应用做好准备,方便我们加入新的功能,甚至写一行新的代码,新的CSS规则。

开发一个新应用的最好你要在脑中想:我正在开发一个大型应用!

文件与目录

文件与目录是我们最先需要组织的东西。在Apache或者其它HTTP服务器通常有一个DocumentRoot 的目录设置,下面的所有子目录都是基于这个设置。

推荐的目录结构:

./css (optionally link)./ext (link)./img (link)./jsindex.html

上面的link标识是指这是一个软连接,指向存有文件的实际目录。这样做的好处是当你下载一个新的Ext版本,并尝试运行,你只需要改变连接指向到这个新版本的目录,不必改写任何一句代码。如果你的应用没有什么异常,就让新版本运作下去吧。如果新版本并不兼容,那么只要把连接指向旧版本的目录就可以了。

  • css 里面放你所有的样式表。如果你有多个项目共用一个样式表,例如一组颜色和字体的设定,你可以将这个目录改用连接。
  • ext 连接去你的Ext JS库
  • img 连接去你的图片目录。它可以有一个icons子目录。
  • js 保存组成这个应用的所有javasript文件
  • index.html 这是你的应用的入口文件。你可以对它改名,也可能需要另外一些的文件去处理登陆验证等。无论怎样,我们只有一个应用程序的入口
  • 其它 你可以建立其它目录或连接,去存放应用程序的其它相关文件(我有一个./classes目录)你可以对它们随意命名,但是最好跟你所有的应用程序保持风格一致。(./server, ./php 是一些不错的示范)

index.html

最简单的index.html内容是:

<html><head>  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">  <link rel="stylesheet" type="text/css" href="./ext/resources/css/ext-all.css">  <link rel="stylesheet" type="text/css" href="./css/application.css">  <script type="text/javascript" src="./ext/adapter/ext/ext-base.js"></script>  <script type="text/javascript" src="./ext/ext-all-debug.js"></script>  <script type="text/javascript" src="./js/application.js"></script>  <title>A Big Application</title></head><body></body></html>

虽然上面的代码运行无误,但是我还是建议为所有文档写上描述性的头部注释到所有文件。同样标记结束的注释也应当写到文件中。具体请参考《文件模式》

js/application.js

我们需要一个文件来写onReady函数,让我们将其命名为application.js吧。它最简单的内容为:

// vim: sw=4:ts=4:nu:nospell:fdc=4/** * An Application * * @author    Ing. Jozef Sakáloš * @copyright (c) 2008, by Ing. Jozef Sakáloš * @date      2. April 2008 * @version   $Id$ * * @license application.js is licensed under the terms of the Open Source * LGPL 3.0 license. Commercial use is permitted to the extent that the  * code/component(s) do NOT become part of another Open Source or Commercially * licensed development library or toolkit without explicit permission. *  * License details: http://www.gnu.org/licenses/lgpl.html */ /*global Ext, Application */ Ext.BLANK_IMAGE_URL = './ext/resources/images/default/s.gif';Ext.ns('Application'); // application main entry pointExt.onReady(function() {     Ext.QuickTips.init();     // code here }); // eo function onReady // eof

你的文件的头部跟底部注释可能不同,但你需确定Ext.BLANK_IMAGE_URL指向你的服务器里面一个1*1像素的透明图像。Ext用它来作图像占位符。如果它指向的路径有误,你可能会遇到各种渲染的问题,例如combo触发时图像丢失,图标丢失等等的问题。

同时你需要为你的应用构造一个全局的对象变量(这里是Application)。

你要确保Ext.onReady是主程序的入口。

css/application.css

你可以将CSS样式表,如果有的话,放到这个文件里面。如果你只有一两个CSS定义就没必要为它们建立一个独立的文件了,这样似乎把它们放在页头的<style>标签里更好。

只不过,请记住你正在开发一个大型应用,所以所有东西都要有自己的容身之所。如果你将样式表放在页头,不久后如果你要处理改变这些样式,你或会忘记它们放在哪里了。

错误的方式

上面这些基本东西都做好后,我们接下来要做什么?让我们开始写代码吧。于是我们坐下来写下如下代码:

var vp = new Ext.Viewport({     layout:'border'    ,items:[        new Ext.grid.GridPanel({            store:new Ext.data.Store({                 proxy:new Ext.data.HttpProxy({ ...

等等。像这样我们很快将会有10,000行代码在我们的application.js文件中,而这样并不是我们想要的。很明显,有些步骤我们遗留了。

正确方式:把它们分离

即使最复杂的一个系统,它都是由一些元素组成功能,再由功能组成子系统,再由子系统组成系统本身。你的应用也不会例外。现在是时候区分开这些功能、组件及它们是如何联系了。

所以,坐下来,想一想,画个草图,写张列表,无论如何,你都得了解这个系统的构成,至少要了解当中最重要的那些。

预配置类

现在你已经做好系统分析并知道会使用哪些组件,你可以开始写第一个。但是怎样写?最好的方式是使用Ext组件的扩展类,在扩展类里面写好所有的设定。这些扩展类我称为预配置类。它们的目的并不是为基类加入新的方法,而仅仅只是为基类设定好参数。例如,可以建立一个“Personnel” grid 类, 里面已经设定column model, store, sorting,editor 等。

如果我们已经有了这个类,我们新建一个Window时就可以这样:

var win = new Ext.Window({     title:'Personnel'    ,width:600    ,height:400    ,items:{xtype:'personnelgrid'}});win.show();

写一个预配置类

[注意:下面的结构并不在所有的环境下都正确,如是有问题,请参考 this post.]

让我们看一个例子来讨论:

Application.PersonnelGrid = Ext.extend(Ext.grid.GridPanel, {     border:false    ,initComponent:function() {        Ext.apply(this, {             store:new Ext.data.Store({...})            ,columns:[{...}, {...}]            ,plugins:[...]            ,viewConfig:{forceFit:true}            ,tbar:[...]            ,bbar:[...]        });         Application.PersonnelGrid.superclass.initComponent.apply(this, arguments);    } // eo function initComponent     ,onRender:function() {        this.store.load();         Application.PersonnelGrid.superclass.onRender.apply(this, arguments);    } // eo function onRender}); Ext.reg('personnelgrid', Application.PersonnelGrid);

看我们都做了些什么?把 Ext.grid.GridPanel 扩展为Application.PersonnelGrid, 并将它注册一个新的xtypepersonnelgrid.

我们为一个普通的grid设定好我们所需的样式,从此我们有了一个新的组件,可以在应用程序中随时随地使用。我们可以这样新建一个实例:

var pg = new Application.PersonnelGrid();

或者使用xtype(延迟实例化)

var win = new Ext.Window({     items:{xtype:'personnelgrid'}    ,....});

组织预配置类

上面的代码不必也不应该在onReady函数里面运行,因为它与DOM结构毫无关系。它只是定义了一个javascript对象,因此它应该写在一个独立的文件中(js/Application.PersonnelGrid.js),然后在index.html header里面引入:

<script type="text/javascript" src="./js/Application.PersonnelGrid.js></script>

到目前为止一切都被安排得很好,我们只需继续写剩下的预配置类,把它们放到 ./js 目录,并在index.html引入,用它们的实例去组成我们的应用。

感觉良好?

其实,还有很多事情要处理。

组件间的沟通

想像我们需要一个border layout,在左边面板有一个超链接列表,在中间面板有一个tab panel。点击一个超链接后会在中间面板新打开一个tab。现在好了,我们应该将这个逻辑放在哪里?事件处理器?构造函数?左面板?还是中间面板?

都不是。为什么?如果我们有一个预配置类创建并显示这个超链接列表,而我们把上述逻辑在这个类中实现。如果程序中这个中间面板对象不存在,这些超链接就失效了。

如果我们将逻辑放在中间面板,结果还是一样:中间面板与左面板必须同时存在。

唯一知道这两个面板是否存在的组件是它们的容器border layout. 这里才是正确的地方。

接下来我们要做的是,border layout 要监听左面板的点击事件,如果是超链接被点击了,则在中间面板打开一个新tab. 具体的例子可以参考这里Saki's Ext Examples

生产系统环境

当我们继续开发我们的程序就会大量的引入javascript文件(我引入了大概80个,而且这个数字每天还在增长)。

最好的方法是以是适当的顺序把所有javascript文件的代码移到一个大文件中,并使用javascript缩小工具和压缩工具。当然,在生产环境中你已经不需要Ext库的debug版本。

所以在生产系统环境中我们需要引入:

  • ext-all.js
  • app-all.js and
  • application.js

关于最小化源代码我们有另一章节another tutorial来深入讨论。

结论

到这里已经差不多了。对于特定的类还有特定的的技术,还有很多其它服务器端或客户端的技巧,但是上面提到的是核心的观点了。


原创粉丝点击