[关闭]
@king- 2015-05-17T19:24:51.000000Z 字数 7314 阅读 1219

ExtJs 4.x 学习文档

web前端开发


Extjs中文文档:http://extjs-doc-cn.github.io/ext4api/
ExtJs导图:http://naotu.baidu.com/viewshare.html?shareId=avhhhfxdvwo4
个人积累分享:http://note.youdao.com/share/?id=5e9a1cf02ebdbd07466ff294127431a9&type=notebook

一、ExtJs包含的主要模块内容:

  1. 工具方法
  2. 视图面板
  3. 数据模型
  4. UI主题

具体结构请查看:ExtJs导图

二、MDM3.0前端目录结构

三、开发流程与规范

MDM3.0 web端界面结构使用MVC的拆分结构,不同的层应该放置在相应的文档目录下。

开发流程:

当有新功能页面产生的时候,我们将在根目录下创建属于该页面的相关同名html文件和js文件。同时在相应的controller文件目录下创建该页面的控制逻辑层文件,在view中创建相关的文件夹,并在该文件夹下存储该页面的视图代码。

(Ps:千万不要因为目录结构和文件类型不同而使得最外层页面文件、Controller文件、View中文件夹名称大小写都相同,不然你会后悔的)

1. 创建相应的文件

2. 引用相关的依赖

app.html

  1. <!-- 使用HTML5规范的文件头描述 -->
  2. <!DOCTYPE html>
  3. <html lang="zh-CN">
  4. <head>
  5. <!-- 这里的两个meta写一个就可以-->
  6. <meta http-equiv="content-type" content="text/html; charset=utf-8">
  7. <meta charset="utf-8">
  8. <title>移动设备管理中心</title>
  9. <script type="text/javascript" src="ext-4/ext-all-debug.js"></script>
  10. <script type="text/javascript" src="ext-4/init.js"></script>
  11. </head>
  12. <body></body>
  13. </html>

这里只需要引用ext-all-debug.js和init.js 就可以了

(延伸阅读:为什么 HTTP header 中 Content-Type 这一条目的写法是 charset 在 content 的属性里面?)

3. 编写布局

app.js

  1. Ext.application({
  2. //引入相关组件类,和java的import导入类一个道理
  3. requires: ['Ext.container.Viewport', 'app.view.custom.BreadCrumb'],
  4. name: 'MDM',//定义命名空间
  5. appFolder: 'app',//描述相关文件所处的文件目录
  6. //定义控制 引入相关类
  7. controllers: [
  8. 'app_Ctrl',
  9. 'Menu'
  10. ],
  11. launch: function() {
  12. Ext.create('Ext.panel.Panel', {
  13. width: justsyConf.width,
  14. height: justsyConf.height,
  15. layout: 'border',//使用border形式布局
  16. items: [{
  17. region: 'north',//设置布局模块位置为north
  18. xtype: 'menubar',//使用组件
  19. split: false
  20. }, {
  21. region: 'north',
  22. xtype: 'breadcrumb',
  23. firstName: justsyLang.appstore,
  24. secondName: justsyLang.appmam
  25. }, {
  26. region: 'west',
  27. xtype: 'panel',
  28. width: 230,
  29. title: '<div class="head-title">' + justsyLang.appClassify + '</div>',
  30. layout: 'fit',//west布局下的panel组件使用fit布局方式
  31. items: [{
  32. xtype: 'apptree'//引入apptree这个组件
  33. }]
  34. }, {
  35. region: 'west',
  36. xtype: 'panel',
  37. cls: 'tran-cross',
  38. bodyCls: 'tran-cross',
  39. width: 6
  40. }, {
  41. region: 'center',
  42. xtype: 'panel',
  43. layout: 'border',
  44. items: [{
  45. region: 'north',
  46. height: 130,
  47. xtype: 'appstoresearch',
  48. title: '<div class="head-title">' + justsyLang.searchRules + '</div>',
  49. }, {
  50. region: 'north',
  51. xtype: 'panel',
  52. cls: 'tran-cross',
  53. bodyCls: 'tran-cross',
  54. height: 5
  55. }, {
  56. region: 'center',
  57. xtype: 'panel',
  58. layout: 'fit',
  59. items: [{
  60. xtype: 'applist',
  61. }]
  62. }, {
  63. region: 'south',
  64. xtype: 'appstoreoperate',
  65. height: 45
  66. }]
  67. }],
  68. renderTo: Ext.getBody() //将上面的内容渲染到html的body中
  69. })
  70. }
  71. });

4. 编写布局中相关面板内容

appList_View.js

  1. //这里的命名就是这个文件的包名,他的规则为【空间名.文件路径名称.文件名称】
  2. Ext.define("MDM.view.app.appList_View", {
  3. extend: 'Ext.grid.Panel', //组件继承的Extjs类
  4. //导入其他需要的Extjs组件类
  5. requires: [
  6. 'Ext.data.*',
  7. 'Ext.grid.*',
  8. 'Ext.util.*',
  9. 'Ext.toolbar.Paging'
  10. ],
  11. //alias 和 xtype 的作用是一样的,为了对现在创建的组件在外面使用而声明一个引用名
  12. alias: 'widget.devicereportlist',
  13. xtype: 'devicereportlist',
  14. //组件的唯一标识,可以通过Ext.getCmp(id)获取到组件
  15. id: 'devicereportlist',
  16. //组件使用的Store文件名
  17. store: 'DeviceOperate_Store',
  18. stripeRows: true,
  19. sortableColumns: true,
  20. viewConfig: {
  21. forceFit: true
  22. }, //自动分配列宽
  23. initComponent: function () {
  24. var store = this.store;
  25. var bbarId = this.bbarId;
  26. //创建列表首列的checkbox组件
  27. var sm = Ext.create('Ext.selection.CheckboxModel', {
  28. showHeaderCheckbox: false
  29. });
  30. Ext.apply(this, {
  31. selModel: sm,//将创建的checkbox赋予gird组件
  32. store: store,
  33. multiSelect: true,
  34. columns: [{
  35. text: justsyLang.deviceNo, //'设备号码',
  36. dataIndex: 'deviceNo',
  37. align: 'left',
  38. flex: 1,
  39. minWidth: 130
  40. }, {
  41. text: justsyLang.deviceName, //'设备名称',
  42. flex: 1,
  43. minWidth: 130,
  44. dataIndex: 'deviceName',
  45. renderer: this.isDeletedFn//使用renderer方法对数据显示前做预处理
  46. }],
  47. //bar 翻页组件配置
  48. bbar: {
  49. xtype: 'pagingtoolbar',
  50. id: bbarId,
  51. alias: 'widget.devicepagingtoolbar',
  52. pageSize: 25,
  53. store: store,
  54. displayInfo: true
  55. }
  56. });
  57. this.callParent();
  58. },
  59. isDeletedFn: function (value) {
  60. if (value == "Y") {
  61. return justsyLang.yes; //"是";
  62. } else if (value == "N") {
  63. return justsyLang.no; //"否";
  64. }
  65. }
  66. });

其他的 appOperate_View.js , appSearch_View.js这些view页面的编写都类似形式

5. Controller添加相关布局操作的逻辑方法

app_Ctrl.js

  1. Ext.define('MDM.controller.Dashboard', {
  2. extend: 'Ext.app.Controller',
  3. views: [
  4. 'app.appList_View',
  5. 'app.appOperate_View',
  6. 'app.appSearch_View'
  7. ],
  8. stores: [
  9. 'appList_Store'
  10. ],
  11. models: [
  12. 'appList_Model'
  13. ],
  14. init: function() {
  15. this.control({
  16. 'appOperate button': {
  17. mouseover: this.showButtonInfo,
  18. mouseout: this.hideButtonInfo
  19. },
  20. 'appSearch button[action=searchBtn]': {
  21. click: this.searchFn
  22. }
  23. }),
  24. }
  25. showButtonInfo: function(obj, e, eOpts) {
  26. CommFun.messBox([obj.id, obj.alertInfo], "button", "add")
  27. },
  28. hideButtonInfo: function(obj, e, eOpts) {
  29. CommFun.messBox([obj.id, obj.alertInfo], "button", "delete");
  30. },
  31. searchFn: function(btn) {
  32. var store = this.getappList_StoreStore();
  33. //获取搜索框中的相关参数
  34. var _form = btn.up('form').getForm().getValues(); //获取方法一
  35. var _form = Ext.getCmp('appSearchId').getForm().getValues(); //获取方法二
  36. /**
  37. * 和服务器发生数据交互的主要有两种方式,
  38. *
  39. * 方法一: 使用 Store 和 Model 封装好的请求格式去直接请求和处理数据,
  40. * 这样的数据会自动处理数据和页面的对应关系,并渲染到页面上
  41. *
  42. * 方法二: 使用传统的Ajax的思维,但是这样的数据ExtJs不会自动去识别View
  43. * 和View建立关系并自动渲染
  44. *
  45. */
  46. //方法一 Store & Model
  47. //将参数交给代理请求方法(为代理请求的请求参数对象赋值)
  48. store.proxy.extraParams = _form;
  49. //发起请求 发起请求方法有多种
  50. store.load(); //方法一 直接load数据
  51. store.loadPage(1); //方法二 获取数据某一页
  52. store.reload(); //方法三 重新load数据
  53. //方法二 Ajax
  54. Ext.Ajax.request({
  55. url: 'justsy/search/device',
  56. method: 'POST',
  57. loadingMask: true, //请求过程中是否需要有loading效果
  58. async: true, //设置Ajax请求类型为同步还是异步请求
  59. success: function(response) {
  60. var jsonObj = Ext.JSON.decode(response.responseText);
  61. if (jsonObj.success) {
  62. //手动获取组件并拿到组件下面的Store数据仓库,使用loadData的形式丢入相关的数据,这里数据应该是Array类型
  63. Ext.getCmp("appListId").getSotre().loadData(jsonObj.content);
  64. //同样是找到组件并获取到Store数据仓库,然后向其插入获取到的数据
  65. Ext.getCmp("appListId").getSotre().insert(jsonObj.conent);
  66. } else {
  67. //对错误进行相关的提示
  68. //这是ExtJs的写法
  69. Ext.MessageBox.alert("title", "errorMsg", callBack);
  70. //这是MDM3.0封装好的写法
  71. CommFun.messBox("title", "errorMsg", "callBack")
  72. }
  73. }
  74. })
  75. }
  76. });

6. 优化界面相关数据处理

  1. Ext.define("MDM.view.app.appList_View", {
  2. extend: 'Ext.grid.Panel', //组件继承的Extjs类
  3. //导入其他需要的Extjs组件类
  4. requires: [
  5. 'Ext.data.*',
  6. 'Ext.grid.*',
  7. 'Ext.util.*',
  8. 'Ext.toolbar.Paging'
  9. ],
  10. //alias 和 xtype 的作用是一样的,为了对现在创建的组件在外面使用而声明一个引用名
  11. alias: 'widget.devicereportlist',
  12. xtype: 'devicereportlist',
  13. //组件的唯一标识,可以通过Ext.getCmp(id)获取到组件
  14. id: 'devicereportlist',
  15. //组件使用的Store文件名
  16. store: 'DeviceOperate_Store',
  17. stripeRows: true,
  18. sortableColumns: true,
  19. viewConfig: {
  20. forceFit: true
  21. }, //自动分配列宽
  22. listeners:{
  23. click:function(me, o){
  24. Ext.getMcp()
  25. }
  26. },
  27. initComponent: function () {
  28. var store = this.store;
  29. var bbarId = this.bbarId;
  30. //创建列表首列的checkbox组件
  31. var sm = Ext.create('Ext.selection.CheckboxModel', {
  32. showHeaderCheckbox: false
  33. });
  34. Ext.apply(this, {
  35. selModel: sm,//将创建的checkbox赋予gird组件
  36. store: store,
  37. multiSelect: true,
  38. columns: [{
  39. text: justsyLang.deviceNo, //'设备号码',
  40. dataIndex: 'deviceNo',
  41. align: 'left',
  42. flex: 1,
  43. minWidth: 130
  44. }, {
  45. text: justsyLang.deviceName, //'设备名称',
  46. flex: 1,
  47. minWidth: 130,
  48. dataIndex: 'deviceName',
  49. renderer: this.isDeletedFn//使用renderer方法对数据显示前做预处理
  50. }],
  51. //bar 翻页组件配置
  52. bbar: {
  53. xtype: 'pagingtoolbar',
  54. id: bbarId,
  55. alias: 'widget.devicepagingtoolbar',
  56. pageSize: 25,
  57. store: store,
  58. displayInfo: true
  59. }
  60. });
  61. this.callParent();
  62. },
  63. //===========================
  64. isDeletedFn: function (value) {
  65. if (value == "Y") {
  66. return justsyLang.yes; //"是";
  67. } else if (value == "N") {
  68. return justsyLang.no; //"否";
  69. }
  70. }
  71. //===========================
  72. });

里面包裹的部分就是一种对数据优化和预处理的方式之一。剩下的方式可以使用过滤器 filters 的方法去处理。
在过滤器 filters 中,我们可以在Store中写或者Model中写,应该依据不同情况去制定,但是在过滤器中修改后的数据,在record 原始数据 中的数据也就直接被修改了。

开发规范:

虽然web前端开发中对规范的遵循不是很严格,但是希望后续的开发中能严格起来,这样对自己代码的维护是很有帮助的。

1. 文件命名建议:

2. 文件内编码建议:

四、常用功能方法

只有定位了组件,你才可能对组件做一系列你想做的操作。

  1. Ext.getCmp(id);//通过ID直接获取组件
  2. Ext.getCmp(id).getComponent(itemId);//通过itemId获取ID组件下的子组件
  3. Ext.getCmp(id).down('xtype/#Id');//通过xtype或者id获取ID组件下的子组件
  4. Ext.getCmp(id).up('xtype/#Id');//通过xtype或者id获取ID组件的上级组件
  5. Ext.get(id);//通过id获取组件的element
  6. Ext.StoreManager.lookup(StoreID);//通过StoreID获取到Store

五、经验分享

1. ExtJs API 如何使用

2. 其他相关内容

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注