[Ext JS 6 By Example 翻译] 第3章 - 基础组件

extjs学习总结 sencha -sdk F:\SvnCodeManage\repository\ext-6.0.0-gpl generate app extjs F:\SvnCodeManage\repository\aa extjs 学习资料 1、onReady 定义在onReady内的语句块会在页面上下文加载完毕后执行 2、define 定义一个类 3、createc初始化一个类的实例 阅读详情

转载自:http://www.jeeboot.com/archives/1219.html



在本章中,你将学习到一些 Ext js 基础组件的使用。同时我们会结合所学创建一个小项目。这一章我们将学习以下知识点:

  • 熟悉基本的组件 – 按钮,文本框,日期选择器等等
  • 表单字段的校验
  • 菜单和工具栏
  • 设计一个表单
  • 计算器程序– 本章的示例项目

本章的主要目的是创建一个表单设计和一个计算器示例项目。以下图分别展示了表单设计和计算器设计。

首先,你观察下列表单设计,你会发现我们使用了大量的控件,例如 label 和文本框。

以下图展示了表单的设计:

1

 

继续,设计计算器程序大量的使用了按钮控件。所以你首要学习的是按钮和 handler 。随后在本章最后我们将会构建一个 计算器程序。在这个过程中,你会知道如何使 view(视图) 和 controller(控制器)进行交互并协同工作。我们还将看到如何绑定 view model(视图模型) 的属性到一个 view(视图) 的字段上。

下图为计算机的设计展示:

1

熟悉基本组件

Ext JS 有大量的优秀的控件,现在让我们开始认识这些基础的组件吧。

Ext.Button

这是一个很常用的控件;handler 是用于处理单击事件,如以下代码所示:

[javascript]  view plain  copy
  1. Ext.create('Ext.Button', {     
  2.     text: 'My Button',     
  3.     renderTo: Ext.getBody(),     
  4.     handler: function() {       
  5.         alert('click');  
  6.     }  
  7. });  

前面代码的输出:

1

 

我在第二章已经介绍过如何运行样例代码,但这里我还想再次重申这一点,此文档中的大部分样例代码都是可以直接运行的。你可以选择在你本地设备上或者在 Sencha Fiddle 上执行这些示例代码。你可以访问Sencha Fiddle 并将上面的代码键入到 launch 函数中,运行并查看结果。如果你访问了 https://fiddle.sencha.com 将会看到下列代码:

[javascript]  view plain  copy
  1. Ext.application({     
  2.     name : 'Fiddle',     
  3.     launch : function() {  
  4.         Ext.Msg.alert('Fiddle', 'Welcome to Sencha Fiddle!');  
  5.     }  
  6. }) ;  


现在粘贴下列的创建按钮的样例代码,运行并查看结果:

[javascript]  view plain  copy
  1. Ext.application({     
  2.     name : 'Fiddle',     
  3.     launch : function() {  
  4.         Ext.create('Ext.Button', {         
  5.             text: 'My Button',         
  6.             renderTo: Ext.getBody(),         
  7.             handler: function() {           
  8.                 alert('click');  
  9.             }  
  10.         });  
  11.     }  
  12. });  


  • 不是所有的代码都可以这样运行,此外并非所有的示例代码都会有视觉呈现。

你还可以使用 listeners 配置添加更多的事件处理器,如以下代码所示:

[javascript]  view plain  copy
  1. Ext.create('Ext.Button', {     
  2.     text: 'My Button',     
  3.     renderTo: Ext.getBody(),     
  4.     listeners: {       
  5.         click: {         
  6.             fn: function(){  
  7.                 //Handle click event           
  8.                 alert('click');  
  9.             }  
  10.         },  
  11.         mouseout: {         
  12.             fn: function(){  
  13.                 //Handle double click event           
  14.                 alert('Mouse out');  
  15.              }  
  16.         }  
  17.     }  
  18. });  


以上代码只是创建了一个简单的按钮,你还可以创建很多不同的按钮,有 link button(连接按钮),menu button(菜单按钮),toggle button(开关按钮) 等等;

来创建一个链接按钮,设置 href 属性,如以下代码所示:

[javascript]  view plain  copy
  1. Ext.create('Ext.Button', {     
  2.     renderTo: Ext.getBody(),     
  3.     text: 'Link Button',     
  4.     href: 'http://www.sencha.com/'   
  5. });  

上面创建的链接按钮输出如图。当点击它则打开链接:

1

 

通过设置 menu 属性,创建一个菜单按钮,如以下代码所示:

[javascript]  view plain  copy
  1. Ext.create('Ext.Button', {     
  2.     text: 'My Button',     
  3.     renderTo: Ext.getBody(),     
  4.     menu: [{       
  5.         text: 'Item 1'  
  6.     }, {       
  7.         text: 'Item 2'  
  8.     }, {       
  9.         text: 'Item 3'  
  10.     }]  
  11. });  

输出如下,当点击时出现下拉菜单:

1

1

Ext.Button 还有许多属性,例如 bind, cls, disabled,html,tooltip,tpl 等等,你可以根据自己需求使用。


Ext.MessageBox

Ext.window.MessageBox 类提供了 message box 实现。Ext. MessageBox 是一个单例对象。你可以使用 MessageBox 弹出一个警告,信息确认,提示输入等等。

下列代码将弹出一个简单的提示信息。这里解释一下 Ext.Msg 是 Ext. Messagebox 类的别名:

[javascript]  view plain  copy
  1. Ext.Msg.alert('Info', 'Document saved!');  


下列代码将弹出一个消息确认框,button 为选择的值,取 yes 或 no :

[javascript]  view plain  copy
  1. Ext.Msg.confirm('Confirm', 'Are you want to cancel the updates?', function(button){     
  2.     if('yes'==button) {  
  3.    
  4.     }   else {  
  5.    
  6.     }  
  7. });  


你也可以自定义这个 message box 如下:

[javascript]  view plain  copy
  1. Ext.MessageBox.show({     
  2.     title:'Save Changes?',     
  3.     msg: 'Do you want to save the file?',     
  4.     buttons: Ext.MessageBox.YESNO,     
  5.     fn: function(button){       
  6.         if('yes'==button){  
  7.    
  8.         }else if('no'==button){  
  9.    
  10.         }     
  11.     },  
  12.     icon: Ext.MessageBox.QUESTION   
  13. }) ;  

上面代码输出如下:

1

表单和表单字段

现在我们看一下都有哪些表单相关的组件。


Ext.form.Panel

这个 form panel (表单面板)继承自 panel  并添加了表单相关的功能,例如字段管理,校验,提交等等。form panel 的默认布局是 anchor layout ,但是如果需要你可以改变这个配置。

form panel 有一个很方便的配置为 fieldDefaults,它可以用于指定表单内所有字段的默认类型。


fields (字段/表单域)

Ext JS 提供了很多内置的表单字段。比较常用的一些字段:

[plain]  view plain  copy
  1. Ext.form.field.Checkbox  
  2.    
  3. Ext.form.field.ComboBox  
  4.    
  5. Ext.form.field.Date  
  6.    
  7. Ext.form.field.File  
  8.    
  9. Ext.form.field.Hidden  
  10.    
  11. Ext.form.field.HtmlEditor  
  12.    
  13. Ext.form.field.Number  
  14.    
  15. Ext.form.field.Radio  
  16.    
  17. Ext.form.field.Text  
  18.    
  19. Ext.form.field.TextArea  
  20.    
  21. Ext.form.field.Time  


我们看一下其中的一些字段的应用。


Ext.form.field.Text

这是一个基本的文本框,它具有很多有用的属性和配置。其中有一个很有用的属性是 vtype 它是用于校验的。 例如以下代码,这个 vtype 属性为 email 用于验证输入内容是否是有效的电子邮箱:

[javascript]  view plain  copy
  1. Ext.create('Ext.form.field.Text', {     
  2.     renderTo: Ext.getBody(),     
  3.     name: 'email',     
  4.     fieldLabel: 'Email',     
  5.     allowBlank: false,     
  6.     vtype: 'email'   
  7. });  

这里 allowBlank 也是一个校验属性。通过设置 allowBlank 属性为 false ,如果这个字段为空白,将会提示校验不通过。


Ext.form.field.Number

number 字段继承自 spinner 字段,spinner 字段则继承自 text 字段,进而的 number 等于是继承了两者。这个 number 字段提供了几个选项来处理数值。下列代码创建了一个数值文本框:

[javascript]  view plain  copy
  1. Ext.create('Ext.form.field.Number', {     
  2.     renderTo: Ext.getBody(),     
  3.     name: 'Count',     
  4.     fieldLabel: 'Count',  
  5.     value: 0,     
  6.     maxValue: 10,     
  7.     minValue: 0   
  8. });  

1

你可以移除下拉按钮,方向键,鼠标滚轮监听,用配置:hideTrigger, keyNavEnabled,和 mouseWheelEnabled 。


Ext.form.field.ComboBox

下列代码创建了一个月份下拉菜单。这个 combobox 有一个配置为 store。 这个 store 是数据源,为此下拉菜单提供数据。store 是属于 ExtJS 中数据包部分, 在接下来的章节中我们会详细介绍的。

combobox 中另一个重要的配置是 queryMode 。这个属性取值可以是 ‘local’ 或者 ‘remote’。如果你设置为 remote 了,那么这个数据源 store 将在运行加载数据时发送请求从远程服务器获取数据:

[javascript]  view plain  copy
  1. var months = Ext.create('Ext.data.Store', {  
  2.     fields: ['abbr', 'name'],  
  3.     data: [{"abbr":"JAN", "name":"January"},  
  4.         {"abbr":"FEB", "name":"February"},     
  5.         {"abbr":"MAR", "name":"March"},  
  6.         {"abbr":"APR", "name":"April"},     
  7.         {"abbr":"MAY", "name":"May"},  
  8.         {"abbr":"JUN", "name":"June"},     
  9.         {"abbr":"JUL", "name":"July"},  
  10.         {"abbr":"AUG", "name":"August"},  
  11.         {"abbr":"SEP", "name":"September"},     
  12.         {"abbr":"OCT", "name":"October"},  
  13.         {"abbr":"NOV", "name":"November"},  
  14.         {"abbr":"DEC", "name":"December"}]   
  15. }) ;  
  16.    
  17. Ext.create('Ext.form.ComboBox', {     
  18.     fieldLabel: 'Choose Month',  
  19.     store: months,     
  20.     queryMode: 'local',     
  21.     displayField: 'name',  
  22.     valueField: 'abbr',     
  23.     renderTo: Ext.getBody()   
  24. });  


以上代码的输出如下:

1


Ext.form.field.HtmlEditor

Ext JS 也有一个非常优秀的 HTML 编辑器,它提供直接在 web 页面上处理文字的能力,如以下代码所示:

[javascript]  view plain  copy
  1. Ext.create('Ext.form.HtmlEditor', {     
  2.     width: 800,     
  3.     height: 200,     
  4.     renderTo: Ext.getBody()   
  5. });  

以上代码输出如下:

 1

表单字段的校验

大多数表单都有自己的校验规则,例如你键入了一个非数值的内容到 number 字段,它将显示一个验证无效的提示。再有这个 text 字段(文本框) 校验属性有  allowBlank,minLength,和 maxLength 。 更进一步的,还有 regex 属性可以使用正则表达式自定义校验。

form panel 的事件

form panel 支持的部分事件:

  • beforeaction: 任意动作执行前触发,例如 submit,load,doAction 这些动作执行时
  • actionfailed: 执行一个动作失败时触发
  • actioncomplete: 在一个动作执行完成之后触发This event will be fired after an action is completed
  • validitychange: 表单键入的内容有效性发生变化时触发
  • dirtychange: 表单的dirty状态改变时触发

表单字段容器

以下是一些 from panel 里很有用的容器。


Ext.form.CheckboxGroup

CheckboxGroup 继承自 FieldContainer 用于组织复选框。下列示例中,复选框组的 items 中所有的项都有相同的 name ;这有助于将得到的值作为一个单一的参数传递给服务器。

[javascript]  view plain  copy
  1. Ext.create('Ext.form.CheckboxGroup', {     
  2.     renderTo: Ext.getBody(),     
  3.     fieldLabel: 'Skills ',     
  4.     vertical: true,     
  5.     columns: 1,     
  6.     items: [{ boxLabel: 'C++', name: 'rb', inputValue: '1' },  
  7.         { boxLabel: '.Net Framework', name: 'rb', inputValue: '2', checked: true },  
  8.         { boxLabel: 'C#', name: 'rb', inputValue: '3' },  
  9.         { boxLabel: 'SQL Server', name: 'rb', inputValue: '4' }]  
  10. }) ;  

以上代码输出如下:

1


Ext.form.FieldContainer

FieldContainer 是很有用的,当你想将一组相关字段附加到一个标签时。

以下代码的输出你会发现一个 label 后面绑定了两个文本框:

[javascript]  view plain  copy
  1. Ext.create('Ext.form.FieldContainer', {  
  2.     renderTo: Ext.getBody(),   
  3.     fieldLabel: 'Name',     
  4.     layout: 'hbox',     
  5.     combineErrors: true,     
  6.     defaultType: 'textfield',  
  7.     defaults: {       
  8.         hideLabel: 'true'  
  9.     },     
  10.     items: [{  
  11.         name: 'firstName',  
  12.         fieldLabel: 'First Name',  
  13.         flex: 2,       
  14.         emptyText: 'First',       
  15.         allowBlank: false  
  16.     }, {       
  17.         name: 'lastName',       
  18.         fieldLabel: 'Last Name',  
  19.         flex: 3,       
  20.         margin: '0 0 0 6',       
  21.         emptyText: 'Last',       
  22.         allowBlank: false  
  23.     }]  
  24. });  

 

Ext.form.RadioGroup

RadioGroup 继承自 CheckboxGroup 用于组织单选按钮。items 中的项都有相同的 name,另外这是单选的,如以下代码所示:

[javascript]  view plain  copy
  1. Ext.create('Ext.form.RadioGroup', {     
  2.     renderTo: Ext.getBody(),     
  3.     fieldLabel: 'Sex ',     
  4.     vertical: true,     
  5.     columns: 1,     
  6.     items: [{   
  7.         boxLabel: 'Male',   
  8.         name: 'rb',   
  9.         inputValue: '1'   
  10.     },{   
  11.         boxLabel: 'Female',   
  12.         name: 'rb',   
  13.         inputValue: '2'   
  14.     }]  
  15. });  

代码输出:

1

提交表单

使用 form 的 submit 方法提交表单。使用 getForm 方法获取表单并 isValid 方法进行提交前的表单内容校验。如以下代码所示:

[javascript]  view plain  copy
  1. var form = this.up('form').getForm();  
  2. if (form.isValid()) {     
  3.     form.submit({       
  4.         url: 'someurl',       
  5.         success: function () {  
  6.    
  7.         },  
  8.         failure: function () {  
  9.    
  10.         }  
  11.     });  
  12. } else {  
  13.     Ext.Msg.alert('Error', 'Fix the errors in the form')  
  14. }  


菜单和工具栏

对于你能想到的任何的菜单和工具栏 Ext JS 提供了最完整的支持。Ext.toolbar.Toolbar 用于构建一个工具栏。默认情况下任何子项在 Ext.toolbar.Toolbar 都是按钮,但是你可以添加任意控件进去,例如一个文本框,一个数值框,一个图标,一个下拉菜单等等。

规范整理你的工具栏中的项,你可以使用 空格(Ext.toolbar.Spacer), 分隔符(Ext.toolbar. Separator),和 使控件右对齐(Ext.toolbar.Fill) 。这里也可以使用快捷方式  ‘ ‘ (空格),’-‘ 和 ‘|’ (都是分隔符,只有很小的差别),和 ‘->‘ (右对齐)。

Ext.menu.Menu 用于构建一个菜单,items 属性中为 Ext.menu.Item 一个个菜单项。

一个简单的代码示例和以下截图的输出:

1

[javascript]  view plain  copy
  1. Ext.create('Ext.toolbar.Toolbar', {     
  2.     renderTo: Ext.getBody(),  
  3.     width: 800,   items: [{  
  4.         text: 'My Button'  
  5.     },{  
  6.         text: 'My Button',       
  7.         menu: [{         
  8.             text: 'Item 1'  
  9.         }, {  
  10.             text: 'Item 2'  
  11.         }, {  
  12.             text: 'Item 3'  
  13.         }]  
  14.     },{  
  15.             text: 'Menu with divider',       
  16.             tooltip: {  
  17.                 text: 'Tooltip info',         
  18.                 title: 'Tip Title'  
  19.             },       
  20.             menu: {         
  21.                 items: [{           
  22.                     text: 'Task 1',  
  23.                     // handler: onItemClick  
  24.                 }, '-', {  
  25.                     text: 'Task 2',  
  26.                     // handler: onItemClick  
  27.                 }, {  
  28.                     text: 'Task 3',  
  29.                     // handler: onItemClick  
  30.                 }]  
  31.             }  
  32.     },'->',{  
  33.         xtype: 'textfield',       
  34.         name: 'field1',  
  35.         emptyText: 'search web site'  
  36.     },'-','Some Info',{  
  37.         xtype: 'tbspacer'  
  38.     },{       
  39.         name: 'Count',       
  40.         xtype: 'numberfield',       
  41.         value: 0,       
  42.         maxValue: 10,       
  43.         minValue: 0,       
  44.         width: 60  
  45.     }]  
  46. });  


设计一个(客户反馈)表单

现在根据之前所学,我们来设计一个表单。

我们将设计如图所示的表单:

1

以下是这个表单的代码。这里我维护着一个这个例子的完整的源码 https://github.com/ananddayalan/extjs-by-example-customer-feedback-form

这里我们所有的组件都在 Viewport 中。 这是一个专用的容器,它代表浏览器里应用的视图区域。

在 Viewport 中我们设置 scrollable 选项将子组件设为滚动的,使用 true 或 false 。也可以取值为 x 或 y 表示只允许水平或垂直滚动:

[javascript]  view plain  copy
  1. Ext.create('Ext.container.Viewport', {  
  2.   scrollable: true,     
  3.   items: [{       
  4.     xtype: 'container',      
  5.     layout: {     
  6.       type: 'hbox',     
  7.       align: 'center',     
  8.       pack: 'center'  
  9.     },       
  10.     items: [ {         
  11.       xtype: 'form',         
  12.       bodyPadding: 20,         
  13.       maxWidth: 700,         
  14.       flex: 1,  
  15.       title: 'Custom Feedback',  
  16.       items:[{  
  17.         xtype: 'fieldcontainer',           
  18.         layout: 'hbox',           
  19.         fieldLabel: 'Name',           
  20.         defaultType: 'textfield',  
  21.         defaults: {             
  22.           allowBlank: false,             
  23.           flex: 1  
  24.         },  
  25.         items: [{             
  26.           name: 'firstName',             
  27.           emptyText: 'First Name  
  28.         }, {            
  29.           name: 'lastName',             
  30.           margin: '0 0 0 5',             
  31.           emptyText: 'Last Name'  
  32.         }]  
  33.       },{           
  34.         xtype: 'datefield',           
  35.         fieldLabel: 'Date of Birth',  
  36.         name: 'dob',           
  37.         maxValue: new Date() /* Prevent entering the future date.*/  
  38.       }, {  
  39.         fieldLabel: 'Email Address',           
  40.         name: 'email',   
  41.         vtype: 'email',  
  42.         allowBlank: false  
  43.       }, {  
  44.         fieldLabel: 'Phone Number',           
  45.         labelWidth: 100,  
  46.         name: 'phone',  
  47.         width: 200,   
  48.         emptyText: 'xxx-xxx-xxxx',  
  49.         maskRe: /[\d\-]/,           
  50.         regex: /^\d{3}-\d{3}-\d{4}$/,  
  51.         regexText: 'The format must be xxx-xxx-xxxx'   
  52.       },{  
  53.         xtype: 'radiogroup',  
  54.         fieldLabel: 'How satisfied with our service?',  
  55.         vertical: true,   
  56.         columns: 1,  
  57.         items: [ {             
  58.           boxLabel: 'Very satisfied',  
  59.           name: 'rb',             
  60.           inputValue: '1'  
  61.         }, {  
  62.           boxLabel: 'Satisfied',             
  63.           name: 'rb', inputValue: '2'  
  64.         }]         
  65.       },{  
  66.         xtype: 'checkboxgroup',  
  67.         fieldLabel: 'Which of these words would you use to describe our products? Select all that apply',  
  68.         vertical: true,           
  69.         columns: 1,           
  70.         items: [{             
  71.           boxLabel: 'Reliable',            
  72.           name: 'ch',             
  73.           inputValue: '1'  
  74.         }]  
  75.       },{  
  76.         xtype: 'radiogroup',  
  77.         fieldLabel: 'How likely is it that you would recommend this company to a friend or colleague?',  
  78.         vertical: false,           
  79.         defaults: { padding: 20 },  
  80.         items: [ {             
  81.           boxLabel: '1',             
  82.           name: 'recommend',             
  83.           inputValue: '1'  
  84.         }],           
  85.         buttons: [{  
  86.           text: 'Submit',            
  87.           handler: function () {  
  88.             var form = this.up('form').getForm();  
  89.             if (form.isValid()) {                 
  90.               form.submit({                   
  91.                 url: 'cutomer/feedback',                   
  92.                 success: function () {},                   
  93.                 failure: function () {}  
  94.               });  
  95.             } else {  
  96.               Ext.Msg.alert('Error', 'Fix the errors in the form')  
  97.             }  
  98.           }  
  99.         }]  
  100.       }]  
  101.     }]  
  102.   }]  
  103. });  


在以上代码中通过在容器级设置 defaultType 属性,这样我们就可以不必在容器的每个子组件里重复的指定 xtype 属性了。这样默认情况下,所有子组件在没有显式指定 xtype 时默认的类型都是 textfield 。

form panel 上有一个 flex 配置用于填补父容器的宽度,同时通过设置 maxWidth 为 700 限制 form panel 的最大宽度。

字段容器使用 hbox 布局将 first name 和 last name 文本框放在一个 label 标签下。

 

写一个计算器应用

现在我们结合目前所学构建一个完整的小项目。这是我们将要构建的计算器的设计:

 1

文件夹结构

这是我们创建的计算器工程的目录结构。这里我不是用 sencha Cmd 生成的项目,只是从 Ext JS 复制了一些必须的文件到项目文件夹中:

1

完整可用的项目在这里: https://github.com/ananddayalan/extjs-by-example-calculator.


App – app.js

在 app.js 文件里我们简单的创建了 Main 视图,作为可移动窗体浮动在浏览器:

[javascript]  view plain  copy
  1. Ext.application({     
  2.     name: 'Calc',     
  3.     launch: function () {  
  4.         Ext.create('Calc.view.main.Main').show();  
  5.     }  
  6. });  


再谈 MVC 和 MVVM

第一章的时候,我们已经介绍过 MVC (Model View Controller) 和 MVVM (Model View ViewModel)。 这个示例项目的代码很好的展示了 视图,控制器,和视图模型之间的区别。

Model (模型)

这代表着数据层。model 保存的数据可以包含数据验证和逻辑。


View (视图)

这一层是用户界面。包含有 button,form,和 message box 等等组件。在我们这次写的计算器应用中 main.js 就是一个很好的视图例子。


Controller (控制器)

控制器处理 view(视图)相关的逻辑,例如 view 的 event(事件)处理,还有任何程序相关逻辑都可以写在这里。


ViewController (视图控制器) 和 Controller (控制器)

在 Ext JS 5 和 6 中,有两种类型的控制器:ViewController 和 Controller。 这个 ViewController 自 Ext JS 5 开始引进的。ViewController 是为一个指定的视图创建的控制器,但是这个控制器也可以交叉其他视图的逻辑。

ViewController 带来了一些新的概念,例如 引用和监听,简化视图与控制之间的关系。同时 View 销毁时 ViewController 也会被销毁,他们具有相同的生命周期,在这个例子中我们没有使用 引用和监听,但是在下一个例子中我们会使用的。

  • 你可以使用 listeners  代替 handler 处理事件

 

View model

view model 封装了 view(视图)所需要的展示逻辑,绑定数据到 view 并且每当数据改变时处理更新。

它有别于 model ,view model 主要是为一个指定的视图而创建的。一个 model 是一个纯粹的数据类并可用于整个应用中,但一个 view model 是起到一个 view 和 model 之间的数据粘合剂的作用。看一下main.js 的 视图模型绑定。


视图 — Main.js

这里我为这个计算器应用创建一个视图为 Main 。这个视图里包含所有的按钮,显示字段等等。相关的事件用 controller 的方法。这个视图的控制器已经使用 controller 配置指定了。

这个视图使用 table 布局,配置为 4 列。CSS 类使用 cls 属性指定。

代码里有附加的注释:

[javascript]  view plain  copy
  1. Ext.define('Calc.view.main.Main', {     
  2.   extend: 'Ext.window.Window',  
  3.   /* 表示在当前视图加载之前先加载这些所需的类*/  
  4.   requires: [ 'Calc.view.main.MainController',  
  5.               'Calc.view.main.MainModel'],     
  6.   xtype: 'app-main',     
  7.   controller: 'main',  
  8.   /* 视图的 view model (视图模型)*/     
  9.   viewModel: { type: 'main' },  
  10.   resizable: false,     
  11.   layout: {       
  12.     type: 'table',       
  13.     columns: 4  
  14.   },    
  15.   /* defaultType 和 defaults 属性是用于 items 内的子组件的,任何子组件都可以覆盖这些配置 */  
  16.   defaultType: 'button',     
  17.   defaults: {       
  18.     width: 50,  
  19.     height: 50,       
  20.     cls: 'btn',       
  21.     handler: 'onClickNumber'  
  22.   },    
  23.   /* 这里我用 Ext.window.Window 的 header 显示计算器的结果。使用 header 你可以在浏览器里移动这个计算器。*/  
  24.   header: {       
  25.     items: [{       
  26.       xtype: 'displayfield',         
  27.       colspan: 4,         
  28.       width: 200,        
  29.       cls: 'display',         
  30.       bind: {   
  31.         value: '{display}'   
  32.       },  
  33.       height: 60,         
  34.       padding: 0  
  35.     }]  
  36.   },  
  37.   items: [{       
  38.     text: 'C',       
  39.     colspan: 2,       
  40.     width: 100,       
  41.     cls: 'btn-green',       
  42.     handler: 'onClickClear'  
  43.   }, {       
  44.     text: '+/-',       
  45.     cls: 'btn-green',       
  46.     handler: 'onClickChangeSign'  
  47.   }, {       
  48.     text: '÷',       
  49.     cls: 'btn-orange',       
  50.     handler: 'onClickOp'  
  51.   },{   
  52.     text: '7'   
  53.   },{   
  54.     text: '8'   
  55.   },{   
  56.     text: '9'   
  57.   },{   
  58.     text: '×',       
  59.     cls: 'btn-orange',       
  60.     handler: 'onClickOp'  
  61.   },{   
  62.     text: '4'  
  63.   },{   
  64.     text: '5'  
  65.   },{   
  66.     text: '6'  
  67.   },{   
  68.     text: '-',       
  69.     cls: 'btn-orange',       
  70.     handler: 'onClickOp'  
  71.   },{   
  72.     text: '1'  
  73.   },{   
  74.     text: '2'  
  75.   },{   
  76.     text: '3'  
  77.   },{   
  78.     text: '+',       
  79.     cls: 'btn-orange',       
  80.     handler: 'onClickOp'  
  81.   },{   
  82.     text: '0',       
  83.     width: 100,       
  84.     colspan: 2  
  85.   },{   
  86.     text: '.',       
  87.     handler: 'onClickDot'  
  88.   },{   
  89.     text: '=',       
  90.     cls: 'btn-orange',       
  91.     handler: 'onClickOp'  
  92.   }]   
  93. });  


控制器 — MainController.js

虽然这个控制器的代码有点长,这是一个非常简单的代码。控制器中有很多方法处理按钮的点击事件,例如运算符和操作数的点击处理。控制器使用了一个 model 为 Main :

[javascript]  view plain  copy
  1. Ext.define('Calc.view.main.MainController', {  
  2.   extend: 'Ext.app.ViewController',  
  3.   alias: 'controller.main',     
  4.   views: ['Calc.view.main.Main'],  
  5.   models: ['Main'],  
  6.   //这个 state 是一个自定义属性,用来跟踪计算器的状态。  
  7.         state: {  
  8.             operatorClicked: false,       
  9.             selectedOperator: null,       
  10.             dotClicked: false,  
  11.             op1: 0,       
  12.             numberClicked: false,       
  13.             sign: true,       
  14.             decimal: false  
  15.         },  
  16.   onClickClear: function () {  
  17.     var vm = this.getViewModel();       
  18.     vm.set('display','0');       
  19.     this.state.selectedOperator=null;  
  20.     this.state.op1=0;       
  21.     this.state.isPositive = true;       
  22.     this.state.decimal = false;       
  23.     this.state.sign = true;  
  24.   },  
  25.   onClickChangeSign: function (btn) {  
  26.     var vm = this.getViewModel();       
  27.     var cur = vm.get('display');       
  28.     if(cur!='0') {         
  29.       if(this.state.sign===true ) {           
  30.         vm.set('display', '-' + cur);  
  31.       }else {  
  32.         vm.set('display', cur.toString().substring(1));  
  33.       }  
  34.      }  
  35.      this.state.sign=!this.state.sign;  
  36.   },  
  37.   onClickOp: function (btn) {  
  38.     if(this.state.selectedOperator!=null && this.state.numberClicked===true){  
  39.       var vm = this.getViewModel();         
  40.       var op2 = parseFloat(vm.get('display'));         
  41.       var op1 = parseFloat(this.state.op1);  
  42.       var result = 0;  
  43.       switch(this.state.selectedOperator){           
  44.         case '+':           
  45.           result = op1 + op2;           
  46.           break;                   
  47.         case '-':           
  48.           result = op1 - op2;  
  49.           break;                   
  50.         case '×':           
  51.           result = op1 * op2;           
  52.           break;                   
  53.         case '÷':           
  54.           result = op1 / op2;           
  55.           break;  
  56.       }  
  57.       vm.set('display', Math.round(result * 100) / 100);  
  58.       this.state.selectedOperator=null;  
  59.     }       
  60.     if(btn.text!='=') {  
  61.       this.state.operatorClicked = true;  
  62.     }  
  63.     this.state.selectedOperator = btn.text;       
  64.     this.state.numberClicked = false;  
  65.   },  
  66.   onClickDot: function (btn) {       
  67.     if(this.state.decimal===false) {         
  68.       var vm = this.getViewModel();         
  69.       vm.set('display', vm.get('display') + '.');  
  70.     }  
  71.   },  
  72.   onClickNumber: function (btn) {  
  73.     this.state.numberClicked = true;       
  74.     if(this.state.selectedOperator ==='='){  
  75.       this.onClickClear();  
  76.     }  
  77.     var vm = this.getViewModel();       
  78.     if(this.state.operatorClicked===true) {         
  79.       this.state.op1= vm.get('display');         
  80.       vm.set('display', btn.text);         
  81.       this.state.operatorClicked=false;  
  82.     }else{  
  83.       var cur = vm.get('display');         
  84.       if(cur == '0') {           
  85.         cur = '';  
  86.       }  
  87.       vm.set('display', cur + btn.text);  
  88.     }     
  89.   }   
  90. });  


 

视图模型 — MainViewModel.js

这个 ViewModel 只有一个属性为 display 。这个用来绑定到计算器显示的值上。这里我们不会分别用一组字段创建模型,此外我们还将会硬编码数据。

[javascript]  view plain  copy
  1. Ext.define('Calc.view.main.MainModel', {     
  2.     extend: 'Ext.app.ViewModel',     
  3.     alias: 'viewmodel.main',     
  4.     data: {       
  5.         display: 0.0  
  6.     }  
  7. });  

在即将到来的章节中你将学习更多关于 模型,视图模型,字段,字段类型,校验 等等。


总结

在本章中,你了解了不同的基本组件,例如 文本框,数字框,按钮,菜单等等。你已经学会如何使用表单字段设计一个表单和我们之前创建了一个简单的计算器项目。

在下一章中,你将学习关于数据包的内容,例如 数据源 ,模型 ,代理等等。store ,model ,这将是有益于处理数据的。

[Ext JS]12.12.1 必填字段组件扩展 Form的字段使用allowBlank:false 设置必填, 但失去焦点时会自动验证, 效果是输入框的边框变成红色,鼠标移动到上面的时候会弹出输入的提示框, 效果如下图: 此外, 在form提交或是调用字段的isValid()或是validate()方式时也会提示验证。 但是这种使用体验要等点击提交按钮才发现有字段没有填值, 是否在一开始就可以提示哪些栏位必须填写呢? 效果可以是在字段的标签前加一个必填的提示符, 类似: 解决方案 结合allowBlank, 在字段标签加必填提示符。 因为字段有很多子 阅读详情

相关推荐

ext js中文开发手册

ext js中文开发手册

Ext JS 6学习文档-第3章-基础组件

Ext JS 6学习文档-第3章-基础组件 基础组件 在本章中,你将学习到一些 Ext JS 基础组件的使用。同时我们会结合所学创建一个小项目。这一章我们将学习以下知识点: 熟悉基本的组件 – 按钮,文本框,日期选择器等等 表单字段的校验 菜单和工具栏 设计一个表单 计算器程序– 本章的示例项目 本章的主要目的是创建一个表单设计和一个计算器示例项目。以下图分别展示了表单...

weixin_30271335的博客 454

科研ABC - The Results Section(SCI论文写作补充)

1 前言 1.1 IMRD格式 1.2 Results部分意义 1.3 Results部分主要内容 2 Results & Discussion关系 2.1 Results & Discussion部分的搭配方式 2.2 Results & Discussion部分的区分 3 Results部分的结构 3.1 Move 1: Set the Stage 3.1....

洋洋洋2020的blog 1620

Ext JS 6.7 中文文档:应用架构介绍(MVC/MVVM)

如何理解 MVC、MVVM 架构?翻译自 Ext JS 6.7.0 官方文档。

Evan 的博客 4072

免费搞定DWG转DXF:ODA File Converter保姆级配置指南(附常见报错解决)

本文详细介绍了如何使用ODA File Converter免费工具实现DWG到DXF的格式转换,包括环境配置、命令行参数解析、编程集成方案及常见问题解决。特别针对网络访问异常、参数配置等实际痛点提供应对策略,帮助用户高效完成工程设计文件的格式转换。

weixin_29291185的博客 6013

ANSYS Workbench实战:用网格自适应搞定超弹性橡胶大变形仿真(附避坑命令流)

本文深入探讨了ANSYS Workbench中超弹性橡胶大变形仿真的网格自适应技术,重点解析了混合U-P单元的应用、非线性自适应网格的实战技巧及材料模型选择的注意事项。通过具体案例和命令流示例,帮助工程师有效解决橡胶仿真中的收敛问题和网格畸变挑战,提升仿真精度和效率。

weixin_42666036的博客 303

[Ext JS 6 By Example 翻译] 第1章 – 入门指南

转载自:http://www.jeeboot.com/archives/1211.html 前言 本来我是打算自己写一个系列的 ExtJS 6 学习笔记的,因为 ExtJS 6 目前的中文学习资料还很少。google 搜索资料时找到了一本国外牛人写的关于 ExtJS 6 的电子书 [Ext JS 6 By Example]。这份资料在 PACKT上卖 35.99 刀的,当然了万能的 g

小桥流水丿小溪 6431

ROS2实战:从零部署Cartographer激光SLAM系统

本文详细介绍了在ROS2 Humble环境下,从零开始部署Cartographer激光SLAM系统的完整实战流程。内容涵盖环境准备、Cartographer安装(APT与源码编译两种方式对比)、工作空间与功能包创建、核心启动文件与Lua配置文件编写、系统构建与可视化启动,以及地图保存与实战调参技巧,帮助开发者快速构建稳定可靠的机器人SLAM应用。

weixin_29213655的博客 248

[Ext JS 6 By Example 翻译] 第2章 - 核心概念

转载请注明出处:http://www.jeeboot.com/archives/1217.html 核心概念 在下一章我们会构建一个示例项目,而在这之前,你需要学习一些在 Ext JS 中的核心概念,这有助于你更容易理解示例项目。这一章我们将学习以下知识点: 类系统,创建和扩展类事件Ext JS 对象的查询容器布局 class system(类系统) Ext JS 提

小桥流水丿小溪 3352

近4000张真实城市场景行人数据集:YOLO训练实战指南

行人检测是计算机视觉在智能驾驶与机器人感知中的基础任务,其核心挑战在于模型对真实道路场景的鲁棒性——尤其在小目标、遮挡、光照变化及中国特有交通参与者(如外卖骑手、接娃家长)下的泛化能力。本文围绕轻量化、高覆盖、强落地性的近4000张实采图像,系统阐释如何构建面向YOLO系列模型的高质量训练数据集:从四维场景采样策略(光照-遮挡-尺度-姿态)出发,解析标注规范对检测精度的关键影响,并说明数据增强需服务于真实干扰源(雨痕、动态模糊、对比度衰减),而非盲目堆叠。该数据集专为已掌握YOLO训练流程的算法工程师、嵌入

weixin_32495691的博客 298

联邦学习中的差分隐私保护详解及python实现

随着数据隐私法规(如 GDPR、CCPA)日益严格,传统将数据集中到云端训练模型的方式面临合规与安全风险。联邦学习通过让各客户端保留本地数据,仅共享模型更新,缓解了数据流动带来的隐私风险。但模型更新仍可能泄露个体信息。为进一步保障隐私,可在本地更新中引入差分隐私(DP)机制,通过向梯度或模型更新中注入随机噪声,防止反向推断原始数据citeturn0search9。

闲人编程的博客 1921

[Ext JS 6 By Example 翻译] 第6章 - 高级组件

转载自:http://www.jeeboot.com/archives/1227.html 高级组件 本章涵盖了高级组件,比如 tree 和 data view。它将为读者呈现一个示例项目为 图片浏览器,它使用 tree 和 data view 组件。以下是本章将要讨论的主题: TreesData views拖放图片浏览器 — 一个示例项目 本章的主要目标是探索 tree

小桥流水丿小溪 1762

双重分组进位跳跃进位链

跳跃进位链

qq_62260432的博客 941

[Ext JS 6 By Example 翻译] 第4章 - 数据包装

转载自:http://www.jeeboot.com/archives/1222.html 数据包装 本章探索 Ext JS 中处理数据可用的工具以及服务器和客户端之间的通信。在本章结束时将写一个调用 RESTful 服务的例子。下面是本章的内容: 模型SchemaStores代理过滤和排序做一个基于 RESTful 的小项目 Model(模型) 一个模型包含字段,字段类

小桥流水丿小溪 2497

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

[Ext JS 6 By Example 翻译] 第8章 - 主题和响应式设计

转载自:http://www.jeeboot.com/archives/1231.html 主题和响应式设计 本章重点在 ExtJS 应用的主题和响应式设计。主要有以下几点内容: SASS 介绍和入门主题响应式设计 SASS 介绍和入门 SASS (Syntactically Awesome Stylesheets) 是一个样式语言,当你使用 SASS 代替 CSS

小桥流水丿小溪 1703

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

上一篇: [Ext JS 6 By Example 翻译] 第2章 - 核心概念
下一篇: [Ext JS 6 By Example 翻译] 第4章 - 数据包装
Sukla
博客等级 码龄11年 56粉丝 242原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值