• Ext面向对象开发实践(turn)


    示例程序简述:

    这个Demo为了演示如将使用GridPanel显示数据,并为GridPanel添加工具条按钮,提供弹出式窗体新增数据。

    使用到的Ext组件

    这个Demo涉及到Ext中的GridPanel,FormPanel和Window三个组件。

    效果图

    现在开始讲解代码,首先看一下创建GridPanel的代码片段

    1. //定义数据列表面板类
    2. PersonListGridPanel = Ext.extend(Ext.grid.GridPanel, {
    3.     insertWin: null,
    4.     updateWin: null,
    5.     constructor: function() {
    6. //添加自定义事件
    7. this.addEvents("rowSelect");
    8. this.insertWin = new InsertPersonInfoWindow();
    9. this.insertWin.on("submit", this.onInsertWinSubmit, this);
    10. this.updateWin = new UpdatePersonInfoWindow();
    11. this.updateWin.on("submit", this.onUpdateWinSubmit, this);
    12.         PersonListGridPanel.superclass.constructor.call(this, {
    13.             renderTo: Ext.getBody(),
    14.             360,
    15.             height: 300,
    16.             frame:true,
    17.             sm: new Ext.grid.RowSelectionModel({
    18.                 singleSelect:true,
    19.                 listeners: {
    20. "rowselect": {
    21.                         fn: function(sm, rowIndex, r) {
    22. this.fireEvent("rowSelect", r); //触发自定义事件
    23.                         },
    24.                         scope: this
    25.                     }
    26.                 }
    27.             }),
    28.             store: new Ext.data.JsonStore({
    29.                     data: [{name: "李宗盛", age: 28, sex: "男"}, {name: "林忆莲", age: 26, sex: "女"}],
    30.                     fields: ["name", "sex", "age"]
    31.             }),
    32.             draggable: false,
    33.             enableColumnMove: false,
    34.             title: "First Grid",
    35. //iconCls:'icon-grid',
    36.             colModel: new Ext.grid.ColumnModel([
    37.                 {header: "Staff Name", 100, menuDisabled: true},
    38.                 {header: "Age", 100, sortable: true, dataIndex: "age", align: "right", tooltip: "这里是提示信息"},
    39.                 {header: "Sex", 100, sortable: true, dataIndex: "sex", align: "center"}
    40.             ]),
    41.             tbar: [{
    42.                 text: "添加人员",
    43.                 handler: function() {
    44. //***************************************************
    45. //如果没有重写InsertPersonInfoWindow的Close方法
    46. //在调用之前需要检查其实例insertWin是否被释放
    47. //使用示例:
    48. //if (!this.insertWin) {
    49. //    this.insertWin = new InsertPersonInfoWindow();
    50. //}
    51. //this.insertWin.show();
    52. //***************************************************
    53. this.insertWin.show();
    54.                 },
    55.                 scope: this
    56.             }, "-", {
    57.                 text: "修改人员",
    58.                 handler: function() {
    59. var r = this.getActiveRecord();
    60. if (!r) return;
    61. //一定要先调用Show方法,而后再调用Load方法,
    62. //否则数据不会被呈现出来
    63. this.updateWin.show();
    64. this.updateWin.load(r);
    65.                 },
    66.                 scope: this
    67.             }, "-", {
    68.                 text: "删除人员",
    69.                 handler: function() {
    70. var r = this.getActiveRecord();
    71. if (!r) return;
    72.                     Ext.MessageBox.confirm("删除", "删除当前人员信息?", function(btn) { 
    73. if(btn == "yes") {
    74. this.delRecord(r);
    75.                         }
    76.                     }, this);
    77.                 },
    78.                 scope: this
    79.             }]
    80.         });
    81.     },
    82.     getActiveRecord: function() {
    83. var sm = this.getSelectionModel();
    84. //没有选中的记录时,是抛出异常还是返回null???????
    85. return (sm.getCount() === 0) ? null : sm.getSelected();
    86.     },
    87.     insert: function(r) {
    88. this.getStore().add(r);
    89.     },
    90.     delRecord: function(r) {
    91. this.getStore().remove(r);
    92.     },
    93.     onInsertWinSubmit: function(win, r) {
    94. this.insert(r);
    95.     },
    96.     onUpdateWinSubmit: function(win, r) {
    97.         alert('onUpdateWinSubmit');
    98.     }
    99. });

    数据维护面板代码

    1. //定义数据维护面板,在后面定义的新增和修改窗体中都会使用到该面板
    2. PersonInfoFormPanel = Ext.extend(Ext.form.FormPanel, {
    3.     constructor: function() {
    4.         PersonInfoFormPanel.superclass.constructor.call(this, {
    5. //title: "Person Info",
    6.             frame: true,
    7.             360,
    8.             labelWidth: 40,
    9.             defaultType: "textfield",
    10.             defaults: { anchor: "92%" },
    11.             items: [{
    12.                 name: "name", //注意,这里使用name属性而不是id,因为PersonInfoFormPanel会被添加和插入两个窗体使用,使用id会有冲突,导致组件不能被正确显示
    13.                 fieldLabel: "Name",
    14.                 allowBlank: false,
    15.                 emptyText: "请输入姓名",
    16.                 blankText: "姓名不能为空"
    17.             }, {
    18.                 name: "age",
    19.                 fieldLabel: "Age",
    20.                 vtype: "age"
    21.             }, {
    22.                 hiddenName: "sex",
    23.                 xtype: "combo",
    24.                 fieldLabel: "Sex",
    25.                 store: new Ext.data.SimpleStore({
    26.                     fields: [
    27.                        {name: 'Sex'}
    28.                     ],
    29.                     data:[["男"], ["女"]]
    30.                 }),
    31.                 mode: 'local',
    32.                 displayField:'Sex',
    33.                 triggerAction: 'all',
    34.                 emptyText:'选择性别...'
    35.             }]
    36.         })
    37.     },
    38.     getValues: function() {
    39. if (this.getForm().isValid()) {
    40. return new Ext.data.Record(this.getForm().getValues());
    41.         }
    42. else {
    43. throw Error("Error Message");
    44.         }
    45.     },
    46.     setValues: function(r) {
    47. this.getForm().loadRecord(r);
    48.     },
    49.     reset: function() {
    50. this.getForm().reset();
    51.     }
    52. });

    对数据的维护有新增和更新两个动作,从设计的角度来讲就需要编写两个窗体对其进行操作。细心的朋友一定会想,新增和更新的动作都是针对相同的数据表,那么能不能只写一个窗体,然后复用呢?答案是肯定的。下面我们就先写一个窗体基类。

    1. //新增,修改窗体基类
    2. PersonInfoWindow = Ext.extend(Ext.Window, {
    3.     form: null,
    4.     constructor: function() {
    5. this.addEvents("submit");
    6. this.form = new PersonInfoFormPanel();
    7. //Ext.apply(this.form, {baseCls: "x-plain"});
    8.         PersonInfoWindow.superclass.constructor.call(this, {
    9.             plain: true,
    10.             360,
    11.             modal: true, //模式窗体
    12.             onEsc: Ext.emptyFn,
    13.             closeAction: "hide",
    14.             items: [this.form],
    15.             buttons: [{
    16.                 text: "确  定",
    17.                 handler: this.onSubmitClick,
    18.                 scope: this
    19.             }, {
    20.                 text: "取  消",
    21.                 handler: this.onCancelClick,
    22.                 scope: this
    23.             }]
    24.         });
    25. //alert(this.onSubmitClick);
    26.     },
    27.     close: function() {
    28. //需要重写CLose方法,
    29. //否则在窗体被关闭其实体会被释放
    30. this.hide();
    31. this.form.reset();
    32.     },
    33.     onSubmitClick: function() {
    34. //alert(Ext.util.JSON.encode(this.form.getValues().data));
    35. try {
    36. this.fireEvent("submit", this, this.form.getValues());
    37. this.close();
    38.         }
    39. catch(_err) {
    40. return;
    41.         }
    42.     },
    43.     onCancelClick: function() {
    44. this.close();
    45.     }
    46. });

    基类写了之后,我们就可以使用继承的方法来编写新进和更新窗体了。

    1. //定义新增数据窗体
    2. InsertPersonInfoWindow = Ext.extend(PersonInfoWindow, {
    3.     title: "添加"
    4. });
    5. //==============================================================================
    6. //定义编辑数据窗体
    7. UpdatePersonInfoWindow = Ext.extend(PersonInfoWindow, {
    8.     title: "修改",
    9.     load: function(r) {
    10. this.form.setValues(r);
    11.     }
    12. });

    为了区分新增和更新窗体,我们在其各自的实现类中为其指定了Title属性,另外在更新窗体类中需要另外添加一个用于加载待编辑数据的方法Load。

    脚本部分算是完成了,下面看看如何在HTML中使用。HTML中的引用代码

    1. <script type="text/javascript">
    2.             Ext.QuickTips.init();
    3. Ext.form.Field.prototype.msgTarget = "side";
    4. Ext.BLANK_IMAGE_URL = "http://localhost:8080/ext-2.2/resources/images/default/s.gif";
    5.             Ext.apply(Ext.form.VTypes, {
    6.                 "age": function(_v) {
    7.                     if (/^\d+$/.test(_v)) {
    8.                         var _age = parseInt(_v);
    9.                         if ((_age > 0) && (_age < 200)) return true;
    10.                     }
    11.                     return false;
    12.                 },
    13.                 "ageText": "年龄必须在0到200之间",
    14.                 "ageMask": /[0-9]/i
    15.             });
    16.             Ext.onReady(function() {
    17.                 new PersonListGridPanel();
    18.             });
    19. </script>

    代码很简洁,也很清晰。只需要创建一个PersonListGridPanel即可,因为它自身包含了新增、修改的窗体对象,而新增和修改窗体中都使用到了负责数据编辑的PersonInfoFormPanel。

    在PersonInfoFormPanel中使用了VTypes进行数据验证。

    新增和修改窗体仅仅是界面,负责将用户在PersonInfoFormPanel中填写的数据传回到ListGrid中以便保存,或是将ListGrid中的数据传递到PersonInfoFormPanel中进行呈现,供用户编辑。

    附上完整的HTML代码和JavaScript代码文件。

    Grid.html

    1. <html>
    2. <head>
    3. <title>Ext Grid</title>
    4. <link rel="stylesheet" type="text/css" href="http://localhost:8080/ext-2.2/resources/css/ext-all.css"/>
    5. <script type="text/javascript" src="http://localhost:8080/ext-2.2/adapter/ext/ext-base.js"></script>
    6. <script type="text/javascript" src="http://localhost:8080/ext-2.2/ext-all.js"></script>
    7. <script type="text/javascript" src="PersonListGridPanel.js"></script>
    8. <script type="text/javascript">
    9.             Ext.QuickTips.init();
    10. Ext.form.Field.prototype.msgTarget = "side";
    11. Ext.BLANK_IMAGE_URL = "http://localhost:8080/ext-2.2/resources/images/default/s.gif";
    12.             Ext.apply(Ext.form.VTypes, {
    13.                 "age": function(_v) {
    14.                     if (/^\d+$/.test(_v)) {
    15.                         var _age = parseInt(_v);
    16.                         if ((_age > 0) && (_age < 200)) return true;
    17.                     }
    18.                     return false;
    19.                 },
    20.                 "ageText": "年龄必须在0到200之间",
    21.                 "ageMask": /[0-9]/i
    22.             });
    23.             Ext.onReady(function() {
    24.                 new PersonListGridPanel();
    25.             });
    26. </script>
    27. </head>
    28. <body>
    29. </body>
    30. </html>

    PersonListGridPanel.js

    1. //定义数据列表面板类
    2. PersonListGridPanel = Ext.extend(Ext.grid.GridPanel, {
    3.     insertWin: null,
    4.     updateWin: null,
    5.     constructor: function() {
    6. //添加自定义事件
    7. this.addEvents("rowSelect");
    8. this.insertWin = new InsertPersonInfoWindow();
    9. this.insertWin.on("submit", this.onInsertWinSubmit, this);
    10. this.updateWin = new UpdatePersonInfoWindow();
    11. this.updateWin.on("submit", this.onUpdateWinSubmit, this);
    12.         PersonListGridPanel.superclass.constructor.call(this, {
    13.             renderTo: Ext.getBody(),
    14.             360,
    15.             height: 300,
    16.             frame:true,
    17.             sm: new Ext.grid.RowSelectionModel({
    18.                 singleSelect:true,
    19.                 listeners: {
    20. "rowselect": {
    21.                         fn: function(sm, rowIndex, r) {
    22. this.fireEvent("rowSelect", r); //触发自定义事件
    23.                         },
    24.                         scope: this
    25.                     }
    26.                 }
    27.             }),
    28.             store: new Ext.data.JsonStore({
    29.                     data: [{name: "李宗盛", age: 28, sex: "男"}, {name: "林忆莲", age: 26, sex: "女"}],
    30.                     fields: ["name", "sex", "age"]
    31.             }),
    32.             draggable: false,
    33.             enableColumnMove: false,
    34.             title: "First Grid",
    35. //iconCls:'icon-grid',
    36.             colModel: new Ext.grid.ColumnModel([
    37.                 {header: "Staff Name", 100, menuDisabled: true},
    38.                 {header: "Age", 100, sortable: true, dataIndex: "age", align: "right", tooltip: "这里是提示信息"},
    39.                 {header: "Sex", 100, sortable: true, dataIndex: "sex", align: "center"}
    40.             ]),
    41.             tbar: [{
    42.                 name: "btnFirst",
    43. //text: "First",
    44.                 iconCls: "x-tbar-page-first",
    45.                 handler: function () {
    46. this.getSelectionModel().selectFirstRow();
    47.                 },
    48.                 scope: this
    49.             }, {
    50.                 name: "btnPrev",
    51. //text: "Prev",
    52.                 iconCls: "x-tbar-page-prev",
    53.                 handler: function () {
    54. this.getSelectionModel().selectPrevious();
    55.                 },
    56.                 scope: this
    57.             }, {
    58.                 name: "btnNext",
    59. //text: "Next",
    60.                 iconCls: "x-tbar-page-next",
    61.                 handler: function () {
    62. this.getSelectionModel().selectNext();
    63.                 },
    64.                 scope: this
    65.             }, {
    66.                 name: "btnLast",
    67. //text: "Last",
    68.                 iconCls: "x-tbar-page-last",
    69.                 handler: function () {
    70. this.getSelectionModel().selectLastRow();
    71.                 },
    72.                 scope: this
    73.             }, "-", {
    74.                 text: "添加",
    75.                 handler: function() {
    76. //***************************************************
    77. //如果没有重写InsertPersonInfoWindow的Close方法
    78. //在调用之前需要检查其实例insertWin是否被释放
    79. //使用示例:
    80. //if (!this.insertWin) {
    81. //    this.insertWin = new InsertPersonInfoWindow();
    82. //}
    83. //this.insertWin.show();
    84. //***************************************************
    85. this.insertWin.show();
    86.                 },
    87.                 scope: this
    88.             }, "-", {
    89.                 text: "修改",
    90.                 handler: function() {
    91. var r = this.getActiveRecord();
    92. if (!r) return;
    93. //如何将数据填充到窗体中?
    94. this.updateWin.show();
    95. this.updateWin.load(r);
    96.                 },
    97.                 scope: this
    98.             }, "-", {
    99.                 text: "删除",
    100.                 handler: function() {
    101. var r = this.getActiveRecord();
    102. if (!r) return;
    103.                     Ext.MessageBox.confirm("删除", "删除当前人员信息?", function(btn) { 
    104. if(btn == "yes") {
    105. this.delRecord(r);
    106.                         }
    107.                     }, this);
    108.                 },
    109.                 scope: this
    110.             }]
    111.         });
    112.     },
    113.     getActiveRecord: function() {
    114. var sm = this.getSelectionModel();
    115. //没有选中的记录时,是抛出异常还是返回null???????
    116. return (sm.getCount() === 0) ? null : sm.getSelected();
    117.     },
    118.     insert: function(r) {
    119. this.getStore().add(r);
    120.     },
    121.     delRecord: function(r) {
    122. this.getStore().remove(r);
    123.     },
    124.     onInsertWinSubmit: function(win, r) {
    125. this.insert(r);
    126.     },
    127.     onUpdateWinSubmit: function(win, r) {
    128.         alert('onUpdateWinSubmit');
    129.     }
    130. });
    131. //==============================================================================
    132. //定义数据维护面板,在后面定义的新增和修改窗体中都会使用到该面板
    133. PersonInfoFormPanel = Ext.extend(Ext.form.FormPanel, {
    134.     constructor: function() {
    135.         PersonInfoFormPanel.superclass.constructor.call(this, {
    136. //title: "Person Info",
    137.             frame: true,
    138.             360,
    139.             labelWidth: 40,
    140.             defaultType: "textfield",
    141.             defaults: { anchor: "92%" },
    142.             items: [{
    143.                 name: "name", //注意,这里使用name属性而不是id,因为PersonInfoFormPanel会被添加和插入两个窗体使用,使用id会有冲突,导致组件不能被正确显示
    144.                 fieldLabel: "Name",
    145.                 allowBlank: false,
    146.                 emptyText: "请输入姓名",
    147.                 blankText: "姓名不能为空"
    148.             }, {
    149.                 name: "age",
    150.                 fieldLabel: "Age",
    151.                 vtype: "age"
    152.             }, {
    153.                 hiddenName: "sex",
    154.                 xtype: "combo",
    155.                 fieldLabel: "Sex",
    156.                 store: new Ext.data.SimpleStore({
    157.                     fields: [
    158.                        {name: 'Sex'}
    159.                     ],
    160.                     data:[["男"], ["女"]]
    161.                 }),
    162.                 mode: 'local',
    163.                 displayField:'Sex',
    164.                 triggerAction: 'all',
    165.                 emptyText:'选择性别...'
    166.             }]
    167.         })
    168.     },
    169.     getValues: function() {
    170. if (this.getForm().isValid()) {
    171. return new Ext.data.Record(this.getForm().getValues());
    172.         }
    173. else {
    174. throw Error("信息不完整");
    175.         }
    176.     },
    177.     setValues: function(r) {
    178. //alert(Ext.util.JSON.encode(r.data));
    179. this.getForm().loadRecord(r);
    180.     },
    181.     reset: function() {
    182. this.getForm().reset();
    183.     }
    184. });
    185. //==============================================================================
    186. //新增,修改窗体基类
    187. PersonInfoWindow = Ext.extend(Ext.Window, {
    188.     form: null,
    189.     constructor: function() {
    190. this.addEvents("submit");
    191. this.form = new PersonInfoFormPanel();
    192. //Ext.apply(this.form, {baseCls: "x-plain"});
    193.         PersonInfoWindow.superclass.constructor.call(this, {
    194.             plain: true,
    195.             360,
    196.             modal: true, //模式窗体
    197.             onEsc: Ext.emptyFn,
    198.             closeAction: "hide",
    199.             items: [this.form],
    200.             buttons: [{
    201.                 text: "确  定",
    202.                 handler: this.onSubmitClick,
    203.                 scope: this
    204.             }, {
    205.                 text: "取  消",
    206.                 handler: this.onCancelClick,
    207.                 scope: this
    208.             }]
    209.         });
    210. //alert(this.onSubmitClick);
    211.     },
    212.     close: function() {
    213. //需要重写CLose方法,
    214. //否则在窗体被关闭其实体会被释放
    215. this.hide();
    216. this.form.reset();
    217.     },
    218.     onSubmitClick: function() {
    219. //alert(Ext.util.JSON.encode(this.form.getValues().data));
    220. try {
    221. this.fireEvent("submit", this, this.form.getValues());
    222. this.close();
    223.         }
    224. catch(_err) {
    225. return;
    226.         }
    227.     },
    228.     onCancelClick: function() {
    229. this.close();
    230.     }
    231. });
    232. //==============================================================================
    233. //定义新增数据窗体
    234. InsertPersonInfoWindow = Ext.extend(PersonInfoWindow, {
    235.     title: "添加"
    236. });
    237. //==============================================================================
    238. //定义编辑数据窗体
    239. UpdatePersonInfoWindow = Ext.extend(PersonInfoWindow, {
    240.     title: "修改",
    241.     load: function(r) {
    242. this.form.setValues(r);
    243.     }
    244. });
  • 相关阅读:
    vim 的配置文件
    linux bash 的自动补全
    linux ping 命令
    linux 安装ifconfig
    dos exist 命令
    linux 用户的添加,组的添加,以及查看
    if else 的.bat 文件
    For 的.bat文件
    rmdir 的.bat文件
    dos set 命令
  • 原文地址:https://www.cnblogs.com/zhukezhuke/p/1549799.html
Copyright © 2020-2023  润新知