【翻译】十大要避免的Ext JS开发方法

原文地址:http://www.sencha.com/blog/top-10-ext-js-development-practices-to-avoid/

作者:Sean Lanktree
Sean is an Ext JS Professional Services Lead at CNX Corporation.


CNX,尽管大多数的Ext JS开发工作需要从0开始创建新的应用程序,偶尔会有客户让我们帮他们解决内部工作上的性能问题、臭虫和结构性问题。我们以“清洁工”这种角色进行工作已经有很长一段时间了,在我们审查过的应用程序中,我们注意到,有一些共同的不明智的编码方法经常会出现。基于过去几年的审查工作,我们列出了十个我们建议的,在Ext JS应用程序中应该避免的开发方法。

1. 过多或不必要的组件嵌套

开发人员最常见的错误之一是没理由的嵌套组件。这样做,会影响性能和也会造成应用程序的不美观,如爽边框火意外的布局行为。在下面的示例1A,在面板内只包含了一个Grid。在这种情况下,该面板是不必要的。如示例1B所示,额外的面板可以取消。要记住的是,表单面板、树面板、标签面板和Grid面板都是从面板扩展的,隐藏,在使用这些组件的时候,应该特别注意不要的嵌套情况。


items: [{
    xtype : 'panel',
    title: ‘My Cool Grid’,
    layout: ‘fit’,
    items : [{
        xtype : 'grid',
        store : 'MyStore',
        columns : [{...}]
    }]
}]

示例1A 不好的:面板(panel)是不必要的


layout: ‘fit’,
items: [{
    xtype : 'grid',
    title: ‘My Cool Grid’,
    store : 'MyStore',
    columns : [{...}]
}]
 

示例1B 好:Grid已经是面板,因而可以直接在Grid中使用任何面板属性


2. 清理未使用组件失败造成内存泄漏

许多开发人员不知道为什么他们的应用程序随着使用时间越长越来越慢。在用户浏览整个应用程序期间清理未使用组件失败是最大的一个原因。在下面的实例2A中,每次用户右键单击Grid的行,都会创建一个新的右键菜单。如果用户保持应用程序处于打开状态并右键单击行上百次,那么,就会有上百个永远不会被摧毁的右键菜单。对于开发人员和用户来说,应用程序“看上去”显示是争取的是因为只有最后一个被创建的菜单能显示在页面上,而且与的则是隐藏的。由于没有创建新菜单并没有清理旧的,应用程序的内存利用率就会不断增长,这最终将导致较慢的操作或浏览器崩溃。

示例2A就很好,由于右键菜单只在Grid初始化时创建一次,并在用户每次右键单击行时重复使用。不过,如果Grid被销毁,右键菜单一直存在,尽管它不再需要。最好的方式是示例2C,在Grid销毁的时候,把右键菜单也销毁。

Ext.define('MyApp.view.MyGrid',{
    extend : 'Ext.grid.Panel',
    columns : [{...}],
    store: ‘MyStore’,
    initComponent : function(){
        this.callParent(arguments);
        this.on({
            scope : this,
            itemcontextmenu : this.onItemContextMenu
        });
    },
 
    onItemContextMenu : function(view,rec,item,index,event){
        event.stopEvent();
        Ext.create('Ext.menu.Menu',{
            items : [{
                text : 'Do Something'
            }]
        }).showAt(event.getXY());
 
    }
});

示例2A 不好:每一次右键单击都会创建菜单,且永远不会被销毁


Ext.define('MyApp.view.MyGrid',{
    extend : 'Ext.grid.Panel',
    store : 'MyStore',
    columns : [{...}],
    initComponent : function(){
        this.menu = this.buildMenu();
        this.callParent(arguments);
        this.on({
            scope : this,
            itemcontextmenu : this.onItemContextMenu
        });
    },
 
    buildMenu : function(){
        return Ext.create('Ext.menu.Menu',{
            items : [{
                text : 'Do Something'
            }]
        });
    },
 
    onItemContextMenu : function(view,rec,item,index,event){
        event.stopEvent();
        this.menu.showAt(event.getXY());
    }
});

示例2B 较好:菜单会在Grid创建时被创建,且每次可重用

Ext.define('MyApp.view.MyGrid',{
    extend : 'Ext.grid.Panel',
    store : 'MyStore',
    columns : [{...}],
    initComponent : function(){
        this.menu = this.buildMenu();
        this.callParent(arguments);
        this.on({
            scope : this,
            itemcontextmenu : this.onItemContextMenu
        });
    },
 
    buildMenu : function(){
        return Ext.create('Ext.menu.Menu',{
            items : [{
                text : 'Do Something'
            }]
        });
    },
 
    onDestroy : function(){
        this.menu.destroy();
        this.callParent(arguments);
    },
 
    onItemContextMenu : function(view,rec,item,index,event){
        event.stopEvent();
        this.menu.showAt(event.getXY());
    }
});

示例2C 最好:Grid被销毁时,右键菜单也被销毁


3.怪物控制器

当看到应用程序拥有一个上千行代码的超级控制器的时候,我们不知道震惊了多少次。我们更倾向于根据应用程序功能拆分控制器。例如,订单处理应用程序可能会有划分条目、出货量、客户查找等控制器。这将使导航和维护代码更容易。

一些开发人员喜欢根据视图拆分控制器。例如,如果一个应用程序有一个Grid和表单,这将会使用一个控制器来管理Grid和使用一个控制器来管理表单。并没有一个“正确”的方式来划分控制器逻辑,只要是一致的就行。要记住,控制器可以与其他控制器进行通信。在示例3A,可以看到如何检索其他的控制器并调用其中的方法。

this.getController('SomeOtherController').runSomeFunction(myParm);

示例3A 获取另一个控制器的引用并调用它的方法。

作为替代,也可以触发任何控制器可以监听到的应用程序层事件。在示例3B和3C,可以看到如何在一个控制器触发一个应用程序层事件并在另外一个控制器监听它。

MyApp.getApplication().fireEvent('myevent');

示例3B 触发一个应用程序层事件

MyApp.getApplication().on({
    myevent : doSomething
});
示例3C 在另一个控制器监听应用程序层事件

注意: 自从Ext JS 4.2开始,使用多个控制器变得更容易了——他们可以触发其他控制器可以直接监听的事件


4.源代码的文件夹结构差

这虽然不影响性能和操作,但会让找跟进应用程序结构变得困难。随着应用程序的增长,如果源代码很有组织,那么寻找源代码以及增加特性或功能就会很容易。我们常常看到许多开发人员会将所有视图(即使是很大的应用程序)如示例4A一样放在一个目录。我们建议如示例4B所示通过逻辑功能来组织视图。

示例4A 不好:所有视图都处于同样层次


示例4B 好:视图根据逻辑功能进行组织

5.全局变量的使用

即使全局变量是不好的已经广为人知,但仍然会在我们审查过的一些应用程序中看到他们的身影。使用全局变量的应用程序可能会有名称冲突等重大问题,并且很难去调试。不使用全局变量,可以在类中定义“属性”,并引用这些属性的getter和setter。

例如,假设应用程序需要记录最后选择的客户。一般情况下会如示例5A那样在应用程序中定义一个变量,这很容易且值可以很便利的被应用程序的其他部分使用。

myLastCustomer = 123456;

示例5A 不好:创建全局变量来存储最后的客户编号

作为替代,好的做法是创建一个用来保存属性的类来代替全局变量。在当前情况下,可以创建一个名为Runtime.js来保存应用程序中要使用到的运行属性。示例5B显示了Runtime.js在源代码结构中的位置。


示例5B Runtime.js文件的位置

示例5C显示了Runtime.js文件的内容,而示例5D显示了如何在app.js中“请求(require)”它。在应用程序中,就可以如5E或5F那样在任何地方“设置(set)”或“获取(get)”属性。

Ext.define(‘MyApp.config.Runtime’,{
    singleton : true,
    config : {
        myLastCustomer : 0   // initialize to 0
    },
    constructor : function(config){
        this.initConfig(config);
    }
});

示例5C 用来为应用程序保存全局属性的Runtime.js文件示例

Ext.application({
    name : ‘MyApp’,
    requires : [‘MyApp.config.Runtime’],
   ...
});

示例5D 在app.js文件中请求Runtime类


MyApp.config.setMyLastCustomer(12345);

示例5E 设置最后客户的方式

MyApp.config.getMyLastCustomer();

示例5F 获取最后客户的方式

6. id的使用

我们不建议在组件上使用id,因为每一个id必须是唯一的。而这样很容易导致不小时使用了相同的id,从而引起重复的DOM id(名称冲突)。相反,应该让框架来处理id的生成。使用Ext JS的组件查询,没有任何理由要为Ext JS组件指定一个id。示例6A显示了一个应用程序中的两段代码,在这里创建了两个不同的保存按钮,而这两个保存按钮的id都为“savebutton”,从而导致了名称冲突。显而易见,在下面的代码很容易找出名称冲突,但在一个大型应用程序中,要确定名称冲突会很困难。

// here we define the first save button
xtype : 'toolbar',
items : [{
    text : ‘Save Picture’,
    id : 'savebutton'
}]
 
// somewhere else in the code we have another component with an id of ‘savebutton’
xtype : 'toolbar',
items : [{
    text : ‘Save Order’,
    id : 'savebutton'
}]

示例6A 不好:为组件分配了重复id将造成名称冲突

替代方法是,如果需要手动确定每一个组件的,可以如示例6B那样使用itemid代替id。这就可以解决命名冲突,并且仍然可以通过itemid来引用组件。通过itemid有许多方法来获取组件的引用。示例6C列出了部分方法。

xtype : 'toolbar',
itemId : ‘picturetoolbar’,
items : [{
    text : 'Save Picture',
    itemId : 'savebutton'
}]
 
// somewhere else in the code we have another component with an itemId of ‘savebutton’
xtype : 'toolbar',
itemId: ‘ordertoolbar’,
items : [{
    text : ‘Save Order’,
    itemId: ‘savebutton’
}]

示例6B 好:使用itemid来创建组件

var pictureSaveButton = Ext.ComponentQuery.query('#picturetoolbar > #savebutton')[0];
 
var orderSaveButton = Ext.ComponentQuery.query('#ordertoolbar > #savebutton')[0]; 
 
// assuming we have a reference to the “picturetoolbar” as picToolbar
picToolbar.down(‘#savebutton’);

示例6C 好:使用itemid引用组件


7.不可靠的组件引用

有时候会看到代码利用组件位置来引用组件。应该避免出现这样的情况,因为有任何条目被增加、移除或嵌入不同的组件,就会导致错误。示例7A显示了几种常见情况。

var mySaveButton = myToolbar.items.getAt(2);
 
var myWindow = myToolbar.ownerCt;

示例7A 不好:避免基于组件位置来获取组件引用

替代方法是,如示例7B那样使用组件查询或者最佳的up或down方法来返回引用。使用这种技术,代码就很少会因以后的结构或组件位置变化而导致错误。

var mySaveButton = myToolbar.down(‘#savebutton’);    // searching against itemId
 
var myWindow = myToolbar.up(‘window’);

示例7B 好:使用组件查询来返回相关引用


8. 不遵守大写/小写命名约定

Sencha在为组件、属性或xtype等等命名的时候,会遵循某些大写/小写标准。为了避免混淆,保持代码清洁,应对遵循相同的标准。示例8A显示几个不正确的情形。示例8B显示了在相同情况下,使用正确的大写/小写命名约定的情形。

Ext.define(‘MyApp.view.customerlist’,{          // should be capitalized and then camelCase
    extend : ‘Ext.grid.Panel’,
    alias : ‘widget.Customerlist’,                       // should be lowercase             
    MyCustomConfig : ‘xyz’,                            // should be camelCase
    initComponent : function(){
        Ext.apply(this,{
            store : ‘Customers’,
            ….
        });
        this.callParent(arguments);
    }
});
 

示例8A 粗体显示的地方为不正确的大写/小写命名

Ext.define(‘MyApp.view.CustomerList’,{      
    extend : ‘Ext.grid.Panel’,
    alias : ‘widget.customerlist’,      
    myCustomConfig : ‘xyz’,            
    initComponent : function(){
        Ext.apply(this,{
            store : ‘Customers’,
            ….
        });
        this.callParent(arguments);
    }
});

示例8B 粗体显示的地方为正确的大写/小写命名

另外,如果触发任何自定义事件,事件的名称应对是小写的。当然,不遵循这些约定,一切都仍然会工作,但为什么要迷失在标准之外并编写不太干净的代码?


9. 将组件约束在父组件的布局

在示例9A,面板总是会有“region:center”属性,因此,当想重用它的时候就可能行不通,例如将它放到“west”区域。

Ext.define('MyApp.view.MyGrid',{
    extend : 'Ext.grid.Panel',
    initComponent : function(){
        Ext.apply(this,{
            store : ‘MyStore’,
            region : 'center',
            ......
        });
        this.callParent(arguments);
    }
});

示例9A 坏:“center”区域不应该放在这里

代替方法是,如示例8B那样,在创建组件的时候才指定布局配置。这样,就可以将组件重用到任何你希望的地方,切不受布局配置的约束。

Ext.define('MyApp.view.MyGrid',{
    extend : 'Ext.grid.Panel',
    initComponent : function(){
        Ext.apply(this,{
            store : ‘MyStore’,
            ......
        });
    }
});
 
// specify the region when the component is created...
Ext.create('MyApp.view.MyGrid',{
    region : 'center' 
});

示例9B 好:在创建组件的时候才知道区域

如示例9C所示,也可以为组件提供一个默认的区域,如果需要,可以重写它。

Ext.define('MyApp.view.MyGrid',{
    extend : 'Ext.grid.Panel',
    region : 'center', // default region
    initComponent : function(){
        Ext.apply(this,{
            store : ‘MyStore’,
            ......
        });
    }
});
 
Ext.create(‘MyApp.view.MyGrid’,{
    region : ‘north’, // overridden region
    height : 400
});

示例9C 也很好:指定默认区域,在需要的时候重写


10. 使代码比所需的更复杂

有很多时候,我们会看到比所需更复杂的代码。这通常是由于对每个组件的可用方法不熟悉造成的。最常见的一种情况是,为每一个表单字段单独从数据记录中加载数据。示例10A就显示这种情况。

//  suppose the following fields exist within a form
items : [{
    fieldLabel : ‘User’,
    itemId : ‘username’
},{
    fieldLabel : ‘Email’,
    itemId : ‘email’
},{
    fieldLabel : ‘Home Address’,
    itemId : ‘address’
}];
 
// you could load the values from a record into each form field individually
myForm.down(‘#username’).setValue(record.get(‘UserName’));
myForm.down(‘#email’).setValue(record.get(‘Email’));
myForm.down(‘#address’).setValue(record.get(‘Address’));

示例10A 不好:为表单字段单独的从记录中加载数据

替代单独加载每一个值的方法是,使用loadRecord方法从记录中为所有字段的数据到表单字段,这只需要一行代码。如示例10B所示,这里的关键是确保表单字段的name属性和记录的字段名称是一样的。

 
items : [{
    fieldLabel : ‘User’,
    name : ‘UserName’
},{
    fieldLabel : ‘Email’,
    name : ‘Email’
},{
    fieldLabel : ‘Home Address’,
    name : ‘Address’
}];
 
myForm.loadRecord(record);

示例10B 好:使用loadRecord方法只需要一行代码就可加载所有表单字段

这只是比必需的更复杂的代码的其中一个例子。而当中的重点是要审视组件的所有方法和和示例,以确保正在使用简单和适当的技术。



CNX公司是Sencha认证选择合作伙伴。Sencha合作伙伴网络是Sencha专业服务器团队的宝贵扩展。

自从1996年以来,CNX一直处于自定义商业应用程序开发的先行者。在2008年,CNX在Ext JS上对它的基于浏览器的用户界面开发进行了标准化,在2010年,又添加了Sencha Touch作为移动开发的标准。我们已经在世界各地,为教育、金融、食品、法律、物流、制造、出版和零售等许多行业的客户创建了一流的Web应用程序。我们的开发团队以芝加哥市中心的公司办公室为基地,可以处理任何规模的项目。CNX可以独立工作或与您的团队一起,以快速、经济高效的方式去实现项目目标。请查阅我们的网站http://www.cnxcorp.com。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
说在前头的 1. 闪烁吧!看看extjs那些美丽的例子。 1.1. 一切从extjs发布包开始 1.2. 看看ext-2.0.2的文档 1.3. 为什么有的例子必须放在服务器上才能看到效果? 1.4. 为什么自己按照例子写的代码,显示出来总找不到图片 1.5. 我们还需要什么? 1.6. 入门之前,都看helloworld。 1.6.1. 直接使用下载的发布包 1.6.2. 只把必要的东西放进项目中 2. 震撼吧!让你知道ext表格控件的厉害。 2.1. 功能丰富,无人能出其右 2.2. 让我们搞一个grid出来耍耍吧。 2.3. grid默认自带的功能 2.4. 按顺序,咱们先要把常见功能讲到 2.4.1. 自主决定每列的宽度 2.4.2. 让grid支持按列排序 2.4.3. 中文排序是个大问题 2.5. 让单元格里显示红色的字,图片,按钮,你还能想到什么? 2.6. 更进一步,自动行号和多选checkbox 2.6.1. 自动行号 2.6.2. 全选checkbox的时间了,请允许我让2.0先上场。 2.7. 分页了吗?分页了吗?如果还没分就看这里吧。 2.7.1. 表面工作,先把分页工具条弄出来。 2.7.2. 自定义分页工具条 2.7.3. 迫不得已,要加上后台脚本了。 2.7.4. 其实分页不一定要踩在脚下,也可以顶在头上。 2.7.5. 谣言说ext不支持前台排序 2.8. 爱生活,EditorGrid。 2.8.1. 旋动舞步,看我们怎么把这个EditorGrid炫出来。 2.8.2. 添加一行,再把它踢掉 2.8.3. 一切就绪,你可以按保存按钮了。 2.8.4. 天马行空,保证提交的数据绝对有效 2.8.5. 限制类型,让用户只能选择我们提供的数据 2.9. 连坐法,关于选择模型 2.10. 2.0有,1.x里没有的那些可怕的控件 2.10.1. 谓之曰PropertyGrid属性表格 2.10.1.1. 小插曲:只能看不能动的PropertyGrid。 2.10.1.2. 小舞曲:强制对name列排序 2.10.1.3. 小夜曲:根据name获得value 2.10.1.4. 奏鸣曲:自定义编辑器 2.10.2. 分组表格,嘻嘻,这是交叉报表吗? 2.11. 午夜怪谈,论可以改变大小,可以拖拽的表格 2.11.1. 先看看怎么拖拽改变表格的大小 2.11.2. 再看怎么在表格里拖动行 2.11.2.1. 无用功 之 同一个表格里拖拽 2.11.2.2. 无间道 之 从这个表格拖到另一个表格 2.11.2.3. 无疆界 之 从表格里拖到树上 2.12. 大步流星,后台排序 2.13. grid与右键菜单 3. 歌颂吧!只为了树也要学ext。 3.1. 真的,我是为了树,才开始学ext的。 3.2. 传统是先做出一棵树来。 3.3. 超越一个根 3.4. 对tree进行统一配置 3.5. 这种装配树节点的形式,真是让人头大。 3.5.1. TreeLoader外传 之 JsonPlugin 3.5.2. TreeLoader外传 之 读取本地json 3.6. jsp的例子是一定要有的 3.7. 让你知道树都可以做些什么 3.7.1. 检阅树形的事件 3.7.2. 右键菜单并非单纯的事件 3.7.3. 默认图标好单调,改一下撒 3.7.4. 偷偷告诉你咋从节点弹出对话框 3.7.5. 小小提示 3.7.6. 给树节点设置超链接 3.8. 灰壳显灵!让我直接修改树节点的名称吧! 3.9. 我拖,我拖,我拖拖拖。 3.9.1. 树形节点的拖拽有三种形式 3.9.2. 用事件控制拖拽 3.9.2.1. 叶子不能append 3.9.2.2. 把节点扔到哪里啦 3.9.2.3. 裟椤双树,常与无常 3.10. 树形过滤器TreeFilter 3.11. TreeSorter对树形排序 4. 祝福吧!把表单和输入控件都改成ext的样式。 4.1. 不用ext的form啊,不怕错过有趣的东西吗? 4.2. 慢慢来,先建一个form再说 4.3. 胡乱扫一下输入控件 4.4. 起点高撒,从comboBox往上蹦 4.4.1. 凭空变出个comboBox来。 4.4.2. 把select变成comboBox。 4.4.3. 破例研究下comboBox的内在本质哟 4.4.4. 嘿嘿~本地的做完了,试试远程滴。 4.4.5. 给咱们的comboBox安上零配件 4.4.6. 每次你选择什么,我都知道 4.4.7. 露一小手,组合上面所知,省市县三级级联。哈哈~ 4.4.7.1. 先做一个模拟的,所有数据都在本地 4.4.7.2. 再做一个有后台的,需要放在服务器上咯 4.5. 把form里的那些控件全部拿出来看看 4.6. form提交数据的三重门 4.6.1. ext中默认的提交形式 4.6.2. 使用html原始的提交形式 4.6.3. 单纯ajax 4.7. 验证苦旅 4.7.1. 不能为空 4.7.2. 最大长度,最小长度 4.7.3. 借助vtype 4.7.4. 自定义验证规则 4.7.5. 算不上校验的NumberField 4.7.6. 使用后台返回的校验信息 4.8. 关于表单内部控件的布局问题 4.8.1. 什么都不做,默认的平铺布局 4.8.2. 分裂,分列 4.8.3. fieldset是个神奇的东西 4.8.4. 当某一天,需要往form加个图片什么的,该咋办? 4.9. 还要做文件上传哟 4.10. 非想非想,单选框多选框 4.10.1. 多选呢checkbox 4.10.2. 单选呢radio 4.11. 自动把数据填充到form里 5. 雀跃吧!超脱了一切的弹出窗口。 5.1. 呵呵~跳出来和缩回去总给人惊艳的感觉。 5.2. 先看看最基本的三个例子 5.2.1. Ext.MessageBox.alert() 5.2.2. Ext.MessageBox.confirm() 5.2.3. Ext.MessageBox.prompt() 5.3. 如果你想的话,可以控制得更多 5.3.1. 可以输入多行的输入框 5.3.2. 再看一个例子呗 5.3.3. 下一个例子是进度条 5.3.4. 动画效果,跳出来,缩回去 5.4. 让弹出窗口,显示我们想要的东东,比如表格 5.4.1. 2.0的弹出表格哦 5.4.2. 向window里加表格 5.4.3. 把form放进对话框里 6. 奔腾吧!让不同的浏览器里显示一样的布局。 6.1. 有了它,我们就可以摆脱那些自称ui设计师的人了。 6.2. ViewPort对整个窗口布局 6.3. 脑袋上有几个标签的tabPanel 6.4. 让布局复杂一点儿 6.5. 向诸位介绍一下各具特色的布局 6.5.1. accordion就是QQ那样的伸缩菜单 6.5.2. CardLayout?其实就是Wizard啦。 6.5.3. 呼呼,TableLayout就是合并行,合并列 7. 低鸣吧!拖拽就像呼吸一样容易。 7.1. 如此拖拽,简直就像与生俱来的本能一样。 7.2. 第一!乱拖。 7.3. 第二!代理proxy和目标target 7.4. yui自远方来,不亦乐乎 7.4.1. Basic,基础 7.4.2. Handles,把手 7.4.3. On Top,总在上边 7.4.4. Proxy,代理 7.4.5. Groups,组 7.4.6. Grid,网格 7.4.7. Circle,圆形 7.4.8. Region,范围 8. 哭泣吧!现在才开始讲基础问题。 8.1. Ext.get 8.2. 要是我们想一下子获得一堆元素咋办? 8.3. DomHelper和Template动态生成html 8.3.1. DomHelper用来生成小片段 8.3.2. 批量生成还是需要Template模板 8.3.3. 醍醐灌顶,功能强劲的模板引擎XTemplate。 8.4. Ext.data命名空间 8.4.1. proxy系列 8.4.1.1. 人畜无害MemoryProxy 8.4.1.2. 常规武器HttpProxy 8.4.1.3. 洲际导弹ScriptTagProxy 8.4.2. reader系列 8.4.2.1. 简单易行ArrayReader 8.4.2.2. 灵活轻便JsonReader 8.4.2.3. 久负盛名XmlReader 8.4.3. 相信你知道怎么做加法 8.5. 跟我用json,每天五分钟 8.5.1. Hello 老爸。 8.5.2. 老妈等等,孩子先上场。 8.5.3. 老妈来了,老妈来啦。 8.5.4. Extjson的支持力度 8.5.5. 反向操作,extjson变成字符串 8.6. 小声说说scope 8.7. 菜单和工具条 8.7.1. 至简至廉的菜单 8.7.2. 丰富一点儿的多级菜单 8.7.3. 单选多选,菜单里搞这套 8.7.4. 小把戏,定制好的菜单 8.7.5. SplitButton让按钮和菜单结合 8.8. 蓝与灰,切换主题 8.9. 悬停提示 8.9.1. 起初,初始化 8.9.2. 诞生,注册提示 8.9.3. 分支,标签提示 8.9.4. 发展,全局配置 8.9.5. 进化,个体配置 8.10. 灵异事件,Ext.state 8.11. 所谓的事件 8.12. 回头谈一谈Ext里的ajax 9. 沉寂吧!我们要自己的控件。 9.1. 下拉树形选择框TreeField 9.2. 带全选的checkbox树形CheckBoxTree 9.3. 带全选的checkbox的grid 9.4. fisheye 9.5. 可以设置时间的日期控件 9.6. JsonView实现用户卡片拖拽与右键菜单 9.7. 下拉列表选择每页显示多少数据 10. 撕裂吧!邪魔外道与边缘学科。 10.1. dwr与ext整合 10.1.1. 无侵入式整合dwr和ext 10.1.2. DWRProxy 10.1.3. DWRTreeLoader 10.1.4. DWRProxy和ComboBox 10.2. localXHR让你在不用服务器就玩ajax 10.3. 在form中使用fckeditor 10.4. 健康快乐动起来,fx里的动画效果 10.5. 悄悄的更新网页内容 A. 常见问题乱弹 A.1. ext到底是收费还是免费 A.2. 怎么查看ext2里的api文档 A.3. 如何在页面中引用ext A.3.1. 顺便说说常见的Ext is not defined错误 A.4. 想把弹出对话框单独拿出来用的看这里 A.5. 想把日期选择框单独拿出来用的看这里 A.6. 听说有人现在还不会汉化ext A.7. 碰到使用ajax获得数据,或者提交数据出现乱码 A.8. TabPanel使用autoLoad加载的页面中的js脚本没有执行 A.9. 有关grid的一些小问题 A.9.1. 如何让grid总所有的列都支持排序 A.9.2. 修改一个grid的ColumnModel和Store A.9.3. 动态为ds添加参数baseParams A.10. 有关tree的一些小问题 A.10.1. 如何选中树中的某个节点 A.10.2. 刷新树的所有节点 A.10.3. 如果取得json中自定义的属性 A.11. 如何使用input type="image" A.12. Ext.Window中的closeAction A.13. 使用同步ajax B. 修改日志 C. 后记 C.1. 2007年12月5日,迷茫阶段 C.1.1. 仇恨 C.1.2. 反省 C.2. 关于ext与dwr整合部分的讨论 C.3. 怎么看文档附件里的范例 C.4. ext开发计划 D. 贡献者列表 D.1. 感谢[飘]的大力支持 D.2. 感谢[吧啦吧啦]的大力支持 D.3. 感谢[游戏人生]的大力支持 D.4. 感谢[綄帥]的大力支持 D.5. 感谢[葡萄]的大力支持 D.6. 感谢[天外小人]的大力支持 D.7. 感谢[我想我是海]的大力支持 D.8. 还要感谢:
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值