目录:
4.1BoxLayout、HBoxLayout、VBoxLayout(箱子布局)
正文
移动应用主要有两种模式:本地应用和移动Web应用。目前以本地应用最为流行,而移动Web应用也日趋流行。这两种模式相当于我们经常说的CS架构和BS架构。
本地应用,简单来说就是通过使用手机操作系统支持的程序语言(例如:iphone的iOS系统使用Objective-C语言,google的android系统则使用Java语言)编写软件,然后安装在手机上的应用软件。本地应用开发可以直接调用手机操作系统的 API(包括UI界面接口、摄像头接口、加速度传感器接口、读写内存地址等等),因此响应速度更快、用户体验更好(界面可制作得很优雅、操作非常流畅)、不受网络的限制。只是目前手机操作系统众多:苹果的iOS、谷歌的Android、微软的Window Phone 7、诺基亚的Symbian、其他厂商的webOS、黑莓等,若一款应用软件想在不同的操作系统上运行,则需要针对不同的平台重新开发(有可能还需要根据手机屏幕的大小进行特定设置),这是一件非常痛苦的事情。
简而言之,本地应用具有可以充分发挥设备硬件和操作系统的特性,运行效率高,完全不受网络限制的优势;也具有开发周期较长、成本较高(需要为各种操作系统进行开发)、不同终端的适配度不理想的劣势。
移动Web应用,简单来理解就是针对移动终端优化过的Web 站点,终端用户通过支持Html5、Css3、Javascript标准的Webkit内核浏览器访问部署在服务器的Web应用。因此移动Web应用具有跨平台、多种终端的广泛适配(降低了开发周期和成本)、实时调整与完善、Web开发者可以快速上手等优势;当然限于手机操作系统的安全限制,移动Web应用还是在硬件功能调用方面有所滞后(譬如:目前还不能直接调用手机的加速度传感器、摄像头)、复杂的用户界面效果难以实现等劣势。不过,随着HTML5的不断发展,移动Web应用也将更加强大。
目前主要的移动Web应用开发框架有:Sencha Touch、JQuery Mobile以及PhoneGap。下面简单介绍一下这三个开发框架。
Sencha Touch
Sencha Touch框架是世界上***个基于HTML 5的Mobile App框架,它可以让Web App看起来像Native App。美丽的用户界面组件和丰富的数据管理,全部基于***的HTML 5和CSS3的 WEB标准,全面兼容Android和iOS设备。Sencha Touch相对来说是一个重量级的移动Web应用框架,适合用于开发业务逻辑比较复杂的移动Web应用。优点:针对触摸屏丰富的UI设计支持复杂交互、纯JavaScript搞定布局、版本稳定性能尚可。
JQuery Mobile
JQuery Mobile 是 jQuery 在手机上和平板设备上的版本,不仅给主流移动平台带来jQuery核心库,而且发布一个完整统一的jQuery移动UI框架,支持全球主流的移动平台,它属于一个轻量级的移动Web应用框架,可以非常便捷的开发出基于Html5的移动网站。优点:超多平台支持、入门简单传统div布局;缺点:UI支持比较简单不适合复杂交互。
PhoneGap
PhoneGap是一个用基于HTML,CSS和JavaScript的,创建移动跨平台移动应用程序的快速开发平台。它使开发者能够利用iPhone,Android,Palm,Symbian,WP7,Bada和Blackberry智能手机的核心功能——包括地理定位,加速器,联系人,声音和振动等,此外PhoneGap拥有丰富的插件,可以以此扩展无限的功能。PhoneGap是免费的,但是它需要特定平台提供的附加软件,例如iPhone的iPhone SDK,Android的Android SDK等,也可以和DW5.5配套开发。使用PhoneGap只比为每个平台分别建立应用程序好一点点,因为虽然基本代码是一样的,但是你仍然需要为每个平台分别编译应用程序。目前PhoneGap缺陷还是蛮多的,比如运行速度慢,UI反应延时。假以时日,随着技术的发展,问题会得到解决的。
具体选择那种移动Web框架,需要从项目组人员技术及业务需求情况出发进行选择:
1、功能简单,只想让现有网站支持手机和平板电脑等移动设备,可考虑jQuery Mobile框架,入门简单而且支持较多平台。
2、想做客户端而且跨平台、丰富的交互,且项目组有熟悉ExtJS的开发人员,Sencha Touch是个不错的选择。
3、如果需要调用到手机操作系统的API,可以把Sencha Touch(或JQuery Mobile)与PhoneGap进行整合开发。
Sencha Touch框架是世界上***个基于HTML 5的Mobile App框架,也是目前为止所发现的***大的应用于移动平台的框架,它将自己定位为框架(Framework)而不是类库(Library),也可以充 分印证这一点。相信随着Sencha Touch的不断发展,移动平台的Web App用户体验设计会得到大幅提升,同时也会对HTML 5和CSS3在移动平台上的普及推广产生很大的促进作用。可以预见,随着HTML 5愈加强大的功能,未来的移动应用将会逐渐向Web App时代迈进。
Sencha Touch是原来的Extjs项目组与jQTouch和Raphael两大项目强强联手后,打造的全新Mobile App框架。
Sencha Touch可以让你的WebApp看起来像Native App。美丽的用户界面组件和丰富的数据管理,全部基于***的HTML 5和CSS3的 WEB标准,全面兼容Android和iOS设备。
Sencha Touch官方列出的几大特性有:
◆基于***的WEB标准 – HTML 5,CSS3,JavaScript。整个库在压缩和gzip后大约80KB,通过禁用一些组件还会使它更小。
◆支持世界上***的设备。Beta版兼容Android和iOS,Android上的开发人员还可以使用一个专为Android定制的主题。
◆增强的触摸事件。在touchstart等标准事件基础上,增加了一组自定义事件数据集成,如tap、swipe、pinch、rotate等。
◆数据集成。提供了强大的数据包,通过Ajax、JSONp、YQL等方式绑定到组件模板,写入本地离线存储。
在查看Sencha Touch自带的Demo以及实际使用中,还可以发现具体不错的功能点:
◆HTML 5地理定位
◆重力感应滚动
◆滚动Touch事件
◆为移动优化的表单元素
◆JSONP代理(跨域数据读取)
◆YQL数据代理(类似查询语言式数据获取)
◆遮罩弹出层
◆Multi-Card布局
◆CSS3 Transitions
◆Tab组件以及滚动列表视图
Sencha Touch的开发环境搭建相当简单,在Eclipse中创建一个Web项目,定好项目的目录结构后,引入Sencha Touch的类库。
Sencha Touch的调试工具,我主要是使用google的chrome浏览器(***版本是chrome15.0.87),下载地址:http://www.google.cn/Chrome。
关于该浏览器及其调试的使用方法可参考:http://www.google.com/support/chrome/bin/static.py?page=guide.cs&guide=29302&hl=cn&printable=1
按我们的通用平台架构,视图层使用了Freemarker模板,因此前台页面一般分为ftl文件和js文件。根据Sencha Touch的特点以及我自己的思考,一个模块一般只需用一个ftl文件,然后在这个文件引入所需用的自定义的js文件(通用的组件js文件,可以考虑放入到freemarker模板中)。
以下就是***个例子的ftl(stFirstExample.ftl)文件内容:
- <@c2.touch title="" cssList=[] jsList=['example/stFirstExample.js']>
- </@c2.touch>
- cssList是用来引入自定义的css3样式文件,jsList是用来引入所需的js文件。
- js(stFirstExample.js)文件内容:
- //创建***个示例的命名空间
- Ext.ns('example', 'example.views');
- //通过Ext.setup方法来参加一个Sencha Touch应用页面,setup方法里可以配置很多属性
- Ext.setup({
- statusBarStyle: 'light',
- onReady: function() {
- //工具栏-toolbar
- varfunBar = {
- xtype: 'toolbar',
- title: 'ST ***个例子',
- dock: 'top', //工具栏放置的位置(必须的属性):top-上,bottom-下,left-左,right-右
- scroll: 'horizontal',
- height:30,
- items: [{
- xtype:'button',
- text: '桌面',
- ui: 'back',
- //iconMask:true,
- //iconCls:'home',
- style:btStyle,
- handler:function(){
- window.location = prefix + '/index.action';
- }
- }]
- };
- //主界面
- varviewport = new Ext.Panel({
- fullscreen:true,
- monitorOrientation:true,
- dockedItems:[funBar],
- items:[{
- html:'hello kitty......'
- }]
- });
- }
- });
可以看到,stFirstExample.js 的***行代码创建了两个命名空间:example和example.views。
第二行代码调用了 Ext.setup() 方法,用以建立一个触控设备的 Web 页面,该方法可以为我们的应用设置不同的启动属性和行为:
◆icon,设置该应用默认的图标;
◆ tabletStartupScreen,该属性设置在平板电脑上的启动图标;
◆ phoneStartupScreen,该属性设置在智能手机上的启动图标;
◆glossOnIcon,该属性设置是否在默认图标上呈现光环效果;
◆onReady,该方法会在页面加载完毕,浏览器中的 DOM 模型已经建立完成时被调用。由于为了保证程序在运行时所依赖的JavaScript 文件都已经加载完毕,我们一般将应用启动的逻辑置于该方法内,类似于 Java 程序的 main 方法。
在onReady方法中,有一个地方我们需用注意的:
◆Ext.Panel对象的dockedItems属性,通过它可以在panel中放置工具栏等组件,可选值有:top-上,bottom-下,left-左,right-右。fullscreen属性为true(默认为false)则强制该panel充满整个屏幕。monitorOrientation属性为true则可以让panel面板监听屏幕方向发生变化时候的事件。
◆dockedItems属性里的对象,必须由docked属性,用以指定放置的位置。
当然js文件也可以通过另外一种方式创建应用:
- //通过Application来创建一个应用
- var FirstApp = new Ext.Application({
- name: 'firstApp',
- useLoadMask: true,
- launch: function () {
- //工具栏-toolbar
- varfunBar = {
- xtype: 'toolbar',
- title: 'ST ***个例子',
- dock: 'top', //工具栏放置的位置(必须的属性):top-上,bottom-下,left-左,right-右
- scroll: 'horizontal',
- height: 30,
- items: [{
- xtype: 'button',
- text: '桌面',
- ui: 'back',
- //iconMask:true,
- //iconCls:'home',
- style: btStyle,
- handler: function(){
- window.location= prefix + '/index.action';
- }
- }]
- };
- //主界面
- var viewport = newExt.Panel({
- fullscreen: true,
- monitorOrientation:true,
- dockedItems: [funBar],
- items: [{
- html: 'hellokitty......'
- }]
- });
- }
- });
Ext.Application实例的初始化,意味者一个Sencha Touch应用的建立,这个类的实例化后,会自动创建一个全局的变量FirstApp,并且同时建立了如下的命名空间:
firstApp
firstApp.views
firstApp.stores
firstApp.models
firstApp.controllers
而launch的方法只会运行一次。
在我们的Web应用开发中,页面的排版、布局很重要,用户就是通过页面操作来完成日常工作的。如果界面布局不合理、操作不方便,用户也不会对系统有好的印象、甚至有可能影响一个项目的成败。我自己的经验是,在开发某个功能模块时,除了仔细属性该模块的功能需求和业务需求外,还会在草稿纸上简单的把该功能的布局画出来(如果美工已经制作有页面模型外)。例如:
Sencha Touch的布局类似Extjs中的布局,常用的有:BoxLayout、HBoxLayout、VBoxLayout、FitLayout、CardLayout。
4.1 BoxLayout、HBoxLayout、VBoxLayout(箱子布局)
BoxLayout是箱子布局,该布局类似于药店里放置中草药的大柜子里一个个小箱子那样,把组件放置在容器中(Container)中。BoxLayout是HBoxLayout和VBoxLayout这两个布局类的父类,一般很少直接使用。
◆HBoxLayout是水平箱子布局,即把组件横排的放置在容器中。
代码清单:
- var viewport = newExt.Panel({
- fullscreen:true,
- //width: 500,
- //height:200,
- margin: '0 0 0 0',
- layout: {
- type: 'hbox', //指定layout布局方式为HBoxLayout
- align: 'stretch' //布局里的‘小容器’拉伸,类似window桌面图片那样,拉伸到整个页面大
- },
- items: [{
- flex: 1, //所占宽度的比率
- //height: 200,
- style: 'border:1pxred solid', //自定义样式
- margin: '0 20 0 0', //设置边框距离
- items: [{
- xtype:'button',
- text:'***',
- margin:6
- }]
- },{
- flex: 2,
- //height: 200,
- style: 'border:1pxred solid',
- margin: '0 20 0 0',
- html: '<divstyle="border:1px red dashed;margin:6px;">第二个小箱子</div>'
- },{
- flex: 3,
- //height: 200,
- style: 'border:1pxred solid',
- items: [{
- xtype:'button',
- text:'第三',
- margin:6
- }]
- }]
- });
有两个属性需要关注一下:
◆align: 'stretch',该属性是设置容器里‘小容器’的对齐方式。
◆flex属性是设置‘小容器’的宽度比率,具体的计算方式请参看文档。
当然还有其他的属性,例如:style、margin、padding,这些属性主要是设置样式的。
◆VBoxLayout垂直箱子布局,即把组件垂直的放置在容器中。
代码清单:
- var viewport = newExt.Panel({
- fullscreen: true,
- //width: 500,
- //height:200,
- margin: '0 0 0 0',
- layout: {
- type: 'vbox', //指定layout布局方式为VBoxLayout
- align:'stretch' //布局里的‘小容器’拉伸
- },
- items: [{
- flex: 1, //所占宽度的比率
- //height: 200,
- style: 'border:1pxred solid',
- margin: '0 0 10 0',
- items: [{
- xtype:'button',
- text:'***',
- margin: 6
- }]
- },{
- flex: 2,
- //height: 200,
- style: 'border:1pxred solid',
- margin: '0 0 10 0',
- html: '<divstyle="border:1px red dashed;margin:6px;">第二个小箱子</div>'
- },{
- flex: 3,
- //height: 200,
- style: 'border:1pxred solid',
- items: [{
- xtype:'button',
- text:'第三',
- margin:6
- }]
- }]
- });
FitLayout是布局的基础类,对应面板布局配置项的名称为fit,使用fit布局将使面板子元素自动充满容器,如果在当前容器中存在多个子面板则只有一个会被显示。
代码清单:
- var viewport = newExt.Panel({
- fullscreen: true,
- //width: 500,
- //height:200,
- margin: '0 0 0 0',
- layout: 'fit', //指定layout布局方式为FitLayout
- items: [{
- style: 'border:1pxred solid',
- html: '<div style="border:1pxred dashed;margin:6px;">***个小箱子</div>'
- },{
- style: 'border:1pxblue solid',
- html: '<div style="border:1pxred dashed;margin:6px;">第二个小箱子</div>'
- }]
- });
CardLayout在Sencha Touch中是最常用的布局,模仿本地应用的页面转换效果主要通过它来体现出来。它是扩展自FitLayout布局,对应面板布局配置项的名称为card。该布局会包含多个子面板,但任何时候都只有一个子面板处于显示状态,这种布局经常用来制作向导和标签页。
各个字面板之间切换的途径是调用setActiveItem方法,该方法接收一个子面板对象或id、索引作为参数。
代码清单:
- //工具栏-toolbar
- var funBar = {
- xtype: 'toolbar',
- title: 'CardLayout例子',
- dock: 'top', //工具栏放置的位置(必须的属性):top-上,bottom-下,left-左,right-右
- scroll: 'horizontal',
- height: 30,
- items: [{
- xtype: 'button',
- text: '桌面',
- ui: 'back',
- //iconMask:true,
- //iconCls:'home',
- style: btStyle,
- handler: function(){
- window.location = prefix + '/index.action';
- }
- },{
- xtype: 'button',
- text: '***个子面板',
- style: btStyle,
- handler: function(){
- changeItem('p1');
- }
- },{
- xtype: 'button',
- text: '第二个子面板',
- style: btStyle,
- handler: function(){
- changeItem('p2');
- }
- }]
- };
- //主界面
- var viewport = newExt.Panel({
- fullscreen: true,
- margin: '0 0 0 0',
- layout: 'card', //指定layout布局方式为CardLayout
- activeItem: 0,
- dockedItems: [funBar],
- items: [{
- id: 'p1',
- style: 'border:1pxred solid',
- html: '<divstyle="border:1px red dashed;margin:6px;">***个小箱子</div>'
- },{
- id: 'p2',
- style: 'border:1pxblue solid',
- html: '<divstyle="border:1px red dashed;margin:6px;">第二个小箱子</div>'
- }]
- });
- //切换子面板
- var changeItem = function(id){
- viewport.setActiveItem(id, 'slide');
- };
- };
用户与系统的交互,绝大部分是通过表单来进行。Sencha Touch的表单与Extjs的表单类似,只是新增了一些html5的元素,例如:url输入框、email输入框、search输入框、Number输入框、slider、toggle等。
表单元素有以下这些,其中有很多都是大家所熟悉的,在此就不做多说明,主要是说明一些新的表单元素及其常用属性,其他(包括组件的方法、事件等)的请大家参照api文档:
◆Text文本输入框
简单的文本输入框,xtype为textfield(注意与extjs的不同哦)。常用的属性有:
id:组件的唯一id,id属性是全部组件都有的。
name:组件的名称,name属性也是全部组件都有的。
label:组件显示的标记(注意与extjs的不同哦)。
labelAlign:label放置的位置,可选值有:left、right、top、bottom。
placeHolder: 输入框为空值时自动显示的值,相当于extjs的emptyText属性。
maxLength:输入框可以输入内容的***长度。
autoCapitalize:是否开启首字母大写(默认为false):true-是,false-否。
useClearIcon:是否使用清除图标:true-当输入框值改变后,右边会显示清除的小图标。
required:标识为必填,只是做一个标识,表单提交时不会做验证。
◆Password密码输入框
密码输入框,xtype类型为passwordfield。
◆Select下拉框
下拉框组件,xtype类型为selectfield。主要的属性:
displayField:下拉框显示的字段名
valueField:下拉框值的字段名(该字段所指向的值将会被传递到后台)
options:下拉选项对象数组,对象的成员名称必须与displayField和valueField的相一致。需要注意的是当select组件设置了store属性,则本属性的值将被忽略。
store:提供给select组件下拉选项的store对象实例,通过该属性可以实现级联下拉选择。
◆DatePicker日期选择
日期选择组件,xtype类型为datepickerfield。主要的属性:
picker:用来创建日期选择器的配置对象或直接使用一个日期选择器实例。例如:
- picker: {
- yearFrom: 1910, //设置开始年份
- cancelButton: '取消', //设置取消按钮上的文字
- doneButton: '完成', //设置完成按钮上的文字
- slotOrder: ['year', 'month', 'day'] //设置日期选择器上显示年月日的顺序
- }
◆Checkbox多选框
多选框组件,xtype类型为checkboxfield。
◆Radio单选框
单选框组件,xtype类型为radiofield。
◆Email电子邮件输入框
邮件输入框组件,xtype类型为emailfield,是文本输入框组件的子类。该组件暂时没有很特别的属性。
◆Url超链接输入框
超链接输入框组件,xtype类型为urlfield,是文本输入框组件的子类。该组件暂时没有很特别的属性。
◆Slider滑动选择器
滑动选择器组件,xtype类型为sliderfield,该组件可以让用户通过手指横向滑动来选择值。主要的属性:
minValue:slider的最小值。
maxValue:slider的***值。
increment:每次滑动的增加值,只能为正整数,默认值为1。
注意:该组件的值不会传递到后台,需要手工调用该组件的getValue()方法获取设置的值,并把这个值设置到一个hidden组件中,以传递给后台程序。可以通过该组件的change事件来检测值的变化情况。
◆ Toggle开关切换器
开关切换器组件,xtype类型为togglefield,该组件是slider组件的子类,它只设置了两个值:0和1。
该组件和slider组件一样,需要手工调用getValue()方法把值设置到一个hidden组件,才能传递给后台程序。
◆Number数字输入框
数组输入框组件,xtype类型为numberfield,是文本输入框组件的子类,但只能输入数字(包括负号与小数点)。
◆Spinner微调器
微调器组件,xtype类型为spinnerfield,是number组件的子类。主要的属性:
minValue:spinner的最小值。
maxValue:spinner的***值。
incrementValue:每次点击-/+按钮时,增加的值。
cycle:循环设置项,该属性为true时,如果值已经到达maxValue设置的值,下一次点击则设置为minValue的值。同样,如果已经达到minValue设置的值,下一次点击则设置为maxValue的值。
◆Textarea文本输入域
文本输入域组件,xtype类型为textareafield,负责多行文字的输入。
◆Search搜索输入框
搜索输入框组件,xtype类型为searchfield,是文本输入框组件的子类。该组件暂时没有很特别的属性。
1) 常用属性:
- baseParams:Object
发送到后台的可选参数(只有当standardSubmit属性为false时,即标准提交方式时,不会把这个属性的参数值传递到后台程序),该属性的类型为Object,例如:{‘entity.title’:’hello kitty’}。
- dockedItems:Object/Array
放置到formpanel的一个或一系列组件,这些依附组件可以放置在formpanel的上下左右的位置。其典型应用是在panel上放置toolbars或tabbars,该属性的类型为一个对象或一个对象数组。
- standardSubmit:Boolean
是否执行一个标准提交,默认为false(非标准提交),该属性的类型为boolean型。如果需要上传附件,则必须执行标准提交,即该属性设置为true。
- waitTpl: Object
设置一个ajax提交进度的模板,例如:提交后弹出‘正在保存数据,请稍等…’的提示。
- record:Ext.data.Model
该属性为只读属性,加载到form中的model实例,该属性的类型是Ext.data.Model。
2) 常用方法:
- getRecord(): Ext.data.Model
该方法返回当前加载到form中的model实例。
- getValues(Boolean enabled): Object
返回一个包含有全部表单元素及其值的对象,对象的属性与表单元素的name属性一致,对于具有相同name属性的checkbox或radio元素,它的值为一个值数组。参数enabled若为true则只返回哪些disabled属性为false或undefined的元素值,false则返回全部。
- load(Ext.data.Model instance): Ext.form.FormPanel
把一个model实例中的数据加载到对应的form元素中(model实例中的name与form元素中name属性一致)。该方法是loadRecord方法的快捷键。通过该方法,我们可方便的把数据设置到form元素中。
- loadRecord(Ext.data.Model instance) : Ext.form.FormPanel
把一个model实例中的数据加载到对应的form元素中(model实例中的name与form元素中name属性一致)。
- removeAll([Boolean autoDestroy]): Array
该方法可以删除form容器中的全部组件,例如:从新增页面保存后跳转到修改页面,这时需要调用该方法把新增页面的表单及其元素全部删除,否则会出现相同名字和id的表单元素。Sencha Touch的页面跳转(setActiveItem方法),是隐藏原来的页面的元素,在该页面的***自动加上后页的html元素。
- reset(): Ext.form.FormPanel
表单重设方法,把表单元素的值设置为表单元素的起始值。
- submit(Object options): Ext.data.Connection
表单提交方法,如果form的standardSubmit属性为true,则执行标准提交,否则执行基于ajax方式把form数据提交到后台。该方法的参数options除非另有说明,一般包含如下的属性值:
url:String,表单提交的目标地址。
method:String,表单提交方式,一般有POST和GET。
params: String/Object,提交到后台的额外参数(即除了表单元素外的参数),如果已设置baseParams属性的话,默认是该属性值。提交时将会调用Ext.urlEncode方法对params值进行编码。
submitDisabled: Boolean,该属性值为true则提交表单中的全部元素,否则只提交disabled为false的表单元素值。
success: Function,表单提交到后台并获得后台程序响应时的回调函数,该函数包含两个参数:form(Ext.FormPanel对象)和result(服务器返回的结果对象),通过该回调函数,我们可根据后台返回的数据进行一定的逻辑处理。
failure: Function,表单提交失败时回调函数,该函数包含两个参数:form(Ext.FormPanel对象)和result(服务器返回的结果对象)。
- scope: Object
回调函数的变量访问。
- updateRecord(Ext.data.Model instance, Boolean enabled):Ext.form.FormPanel
把表单元素中的数据更新到model实例中。
表单数据加载,可以通过load方法从一个已有的model实例中把数据设置到表单元素中,也可以通过ajax从后台获取数据,然后通过load方法加载数据到表单元素中。
1) 从model实例中加载
- //定义一个model
- Ext.regModel('PersonInfo', {
- fields: [
- {name:'entity.linkman',type:'string'},
- {name:'entity.password', type:'string'},
- {name:'entity.sex',type:'string'},
- {name:'entity.introduce',type:'string'}
- ]
- });
- //创建model实例数据
- var person = Ext.ModelMgr.create({
- 'entity.linkman': 'hellokitty',
- 'entity.password' : 'hellokitty',
- 'entity.sex': 'm',
- 'entity.introduce' : '人见人爱 车见车载'
- }, 'PersonInfo');
- //加载数据到form元素中
- Ext.getCmp('frmInfo').load(person);
2) 通过Ajax从后台获取数据并加载到表单中
该方式只是多了通过ajax从后台获取数据的步骤,其他的都与方式一是一样的,在此不多说了。
表单数据提交有两种方式:标准提交和ajax数据提交。为了更好的增强用户的操作体验,我们一般是采取ajax提交方式,即使是附件上传功能,也可以通过提交到一个隐藏iframe方式,模拟ajax提交。
表单数据的提交通常是通过form组件的submit方法提交。
代码清单:
- //提交数据
- submitForm: function(sendFlag){
- //验证数据
- if(!this.validate()){
- return;
- }
- var_scope = this;
- vartipMask = '正在保存便函,请稍等...';
- //是否发送标识
- Ext.getCmp('issended').setValue(sendFlag);
- if(sendFlag== '1'){
- tipMask = '正在发送便函,请稍等...';
- }
- //弹出正在保存的提示
- varcmpMask = Ext.getBody();
- loadMask(cmpMask,iconPath, tipMask);
- //设置按钮失效
- vararrButton = [Ext.getCmp('btnSave'), Ext.getCmp('btnSend')];
- enableButton(arrButton,false);
- var form= Ext.getCmp('frmInfo');
- form.submit({
- url: this.saveURL,
- method: 'POST',
- success: function(thisForm,action){
- unLoadMask(cmpMask);
- //实体ID
- var buId =action.result;
- varsaveTip = '成功保存便函信息!';
- if(sendFlag== '1'){
- saveTip = '成功发送便函信息!';
- }
- var sa =Ext.Msg.alert('', saveTip);
- setTimeout(function(){
- sa.hide();
- enableButton(arrButton, true);
- }, 1500);
- //保存附件
- _scope.saveAttach(_scope, buId, sendFlag);
- },
- failure: function(thisForm,action){
- unLoadMask(cmpMask);
- enableButton(arrButton, true);
- if(action.result){
- Ext.Msg.alert('',action.result);
- }else{
- Ext.Msg.alert('', '提交失败,表单数据不完整!');
- }
- }
- });
- }
若是需要上传附件,则必须使用标准提交,且需要设置form的enctype属性。该属性的设置,一般是在formpanel的afterrender监听器中设置:
- {
- xtype: 'form',
- id: 'frmAttach',
- margin: '0 0 0 0',
- standardSubmit: true, //只有标准提交(即不通过ajax方式提交),才可以上传附件
- items: [{
- xtype: 'hiddenfield',
- id: 'attRefId',
- name: 'entity.id'
- },{
- html: '<iframe id="ifrmUpload"name="ifrmUpload" style="display:none"></iframe>'
- }, this.renderAttachInfo(this, null)],
- listeners: {
- afterrender: function(frm){
- //设置form的属性
- Ext.getDom('frmAttach').enctype = 'multipart/form-data';
- Ext.getDom('frmAttach').method = 'POST';
- Ext.getDom('frmAttach').target = 'ifrmUpload';
- }
- }
- };
根据Sencha Touch技术框架的特点,前台展示的绝大部分数据都是通过ajax方式获取,譬如列表数据的获取、表单数据的获取等等。列表数据的获取,一般是通过store组件和list组件进行结合;表单数据的获取通常使用Ext.request方式获取。
列表数据的获取代码清单:
- //数据列表
- renderListData: function(){
- //定义变量和函数的作用范围
- var _scope = this;
- var st = newExt.data.Store({
- model: _scope.model, //store组件使用的Ext.data.Model
- //sorters: 'crtdt',
- autoLoad: true, //是否自动加载数据
- proxy: {
- type: 'ajax',
- actionMethods: 'POST',
- url:_scope.url, //数据获取的url地址
- extraParams:_scope.extraParams, //请求的额外参数
- startParam:'start',
- limitParam:'limit',
- reader: {
- type: 'json', //reader类型-默认jsonReader,
- root: undefined,//reader root-默认undefined
- }
- },
- listeners: {
- beforeload: function(st,oper){
- oper.start = _scope.start; //设置分页起始记录
- oper.limit = _scope.limit; //设置每页显示记录数
- },
- load: function(st,records, successful){
- if(successful){
- //获取后台返回的记录总数属性
- _scope.totalNum =st.getProxy().getReader().rawData.total;
- //分页按钮控制
- _scope.controlPageButtons();
- //回调外部函数-返回结果给外部函数
- if(_scope.callbackFn){
- _scope.callbackFn({listId:_scope.listId,total:_scope.totalNum});
- }
- }
- }
- }
- });
- //创建并返回list组件
- return newExt.List({
- id: _scope.listId,
- //multiSelect: true,
- //simpleSelect: true,
- scroll: 'vertical',
- store:st, //store组件对象
- emptyText: '<divstyle="margin:2px;">'+_scope.emptyText+'</div>',
- loadingText: '正在获取数据',
- itemTpl: _scope.itemTpl, //列表显示的模板
- listeners: {
- itemtap: function(lt, idx, item,e){
- //点击列表记录时执行的函数
- if(_scope.itemTapFn){
- var record =lt.getStore().getAt(idx);
- _scope.itemTapFn({listId:_scope.listId,record:record}, _scope.fnScope);
- }
- }
- }
- });
- }
- 通过Ext.request方式获取数据的代码清单:
- //获取数据
- fetchData: function(){
- var _scope= this;
- Ext.Ajax.request({
- method: 'POST',
- url: prefix + '/doc/letter/manager!fetchEditData.action',
- params: {
- 'entity.id':_scope.entityId //传递给后台的参数
- },
- success: function(response,opts){
- varobjResp = Ext.decode(response.responseText);
- if(objResp.success){
- varobjData = Ext.decode(objResp.result);
- //调用自定义的函数把数据设置到form中
- _scope.loadDataToForm(_scope,objData);
- }else{
- Ext.Msg.alert(objResp.result);
- }
- },
- failure: function(response,opts){
- Ext.Msg.alert('很抱歉,由于网络原因获取数据出错!');
- }
- });
- }
鉴于目前移动网络的网速以及手机设备浏览器的处理能力,为了提高应用响应的速度与用户的操作体验,使用Sencha Touch开发移动应用时需要注意一些情况:
◆后台的数据传输要尽量精简,前台js书写需要尽量简洁。
◆界面要尽量精简以及少用图片,要保证应用的流畅,毕竟移动网络的网速远比不上宽带。
◆应用入口尽量要分模块,因为Sencha Touch整个应用只有一个入口的话,需要引入大量的js文件,这样可能会导致***个页面的响应速度很慢(js文件需要下载到浏览器)。
◆一些通用功能尽量组件化,提高组件的重用。
原文地址:http://blog.csdn.net/ejbcreate/article/details/7180169