您的位置:首页 > 其它

移动Web应用开发技术讲解-Sencha Touch 1.1

2012-01-06 09:45 357 查看
【本想上传整份文档及其配套例子,无奈不支持 :-( 】

移动Web应用开发技术讲解

Sencha Touch 1.1

廖 章
2011年12月

目 录
第一章 移动应用现状.. 2

1.1 移动应用模式及其各自优劣势... 2

1.2 移动Web应用开发框架... 2

第二章 Sencha Touch框架的介绍.. 4

第三章 Sencha Touch第一个例子.. 6

3.1 发环境的搭建与调试工具... 6

3.2 第一例子... 7

第四章 Sencha Touch布局介绍.. 10

4.1 BoxLayout、HBoxLayout、VBoxLayout(箱子布局)... 10

4.2 FitLayout(自适应布局)... 13

4.3 CardLayout(卡片式布局)... 13

第五章 Sencha Touch表单.. 16

5.1 表单元素... 16

5.2 表单常用属性与常用方法... 19

5.3 表单数据加载... 21

5.4 表单数据提交... 22

第六章 数据的获取.. 24

第七章 总结.. 26

第一章 移动应用现状
1.1 移动应用模式及其各自优劣势

移动应用主要有两种模式:本地应用和移动Web应用。目前以本地应用最为流行,而移动Web应用也日趋流行。这两种模式相当于我们经常说的CS架构和BS架构。

本地应用,简单来说就是通过使用手机操作系统支持的程序语言(例如:iphone的iOS系统使用Objective-C语言,google的android系统则使用Java语言)编写软件,然后安装在手机上的应用软件。本地应用开发可以直接调用手机操作系统的 API(包括UI界面接口、摄像头接口、加速度传感器接口、读写内存地址等等),因此响应速度更快、用户体验更好(界面可制作得很优雅、操作非常流畅)、不受网络的限制。只是目前手机操作系统众多:苹果的iOS、谷歌的Android、微软的WindowPhone 7、诺基亚的Symbian、其他厂商的WebOS、黑莓等,若一款应用软件想在不同的操作系统上运行,则需要针对不同的平台重新开发(有可能还需要根据手机屏幕的大小进行特定设置),这是一件非常痛苦的事情。

简而言之,本地应用具有可以充分发挥设备硬件和操作系统的特性,运行效率高,完全不受网络限制的优势;也具有开发周期较长、成本较高(需要为各种操作系统进行开发)、不同终端的适配度不理想的劣势。

移动Web应用,简单来理解就是针对移动终端优化过的Web 站点,终端用户通过支持Html5、Css3、Javascript标准的Webkit内核浏览器访问部署在服务器的Web应用。因此移动Web应用具有跨平台、多种终端的广泛适配(降低了开发周期和成本)、实时调整与完善、Web开发者可以快速上手等优势;当然限于手机操作系统的安全限制,移动Web应用还是在硬件功能调用方面有所滞后(譬如:目前还不能直接调用手机的加速度传感器、摄像头)、复杂的用户界面效果难以实现等劣势。不过,随着HTML5的不断发展,移动Web应用也将更加强大。

1.2 移动Web应用开发框架

目前主要的移动Web应用开发框架有:Sencha Touch、JQuery Mobile以及PhoneGap。下面简单介绍一下这三个开发框架。

u Sencha Touch:Sencha Touch框架是世界上第一个基于HTML 5的Mobile App框架,它可以让Web App看起来像Native App。美丽的用户界面组件和丰富的数据管理,全部基于最新的HTML 5和CSS3的 WEB标准,全面兼容Android和iOS设备。SenchaTouch相对来说是一个重量级的移动Web应用框架,适合用于开发业务逻辑比较复杂的移动Web应用。优点:针对触摸屏丰富的UI设计支持复杂交互、纯JavaScript搞定布局、版本稳定性能尚可。

u JQuery Mobile:JQuery Mobile 是 jQuery 在手机上和平板设备上的版本,不仅给主流移动平台带来jQuery核心库,而且发布一个完整统一的jQuery移动UI框架,支持全球主流的移动平台,它属于一个轻量级的移动Web应用框架,可以非常便捷的开发出基于Html5的移动网站。优点:超多平台支持、入门简单传统div布局;缺点:UI支持比较简单不适合复杂交互。

u 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进行整合开发。

第二章 SenchaTouch框架的介绍
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官方列出的几大特性有:

u 基于最新的WEB标准 – HTML 5,CSS3,JavaScript。整个库在压缩和gzip后大约80KB,通过禁用一些组件还会使它更小。

u 支持世界上最好的设备。Beta版兼容Android和iOS,Android上的开发人员还可以使用一个专为Android定制的主题。

u 增强的触摸事件。在touchstart等标准事件基础上,增加了一组自定义事件数据集成,如tap、swipe、pinch、rotate等。

u 数据集成。提供了强大的数据包,通过Ajax、JSONp、YQL等方式绑定到组件模板,写入本地离线存储。

在查看Sencha Touch自带的Demo以及实际使用中,还可以发现具体不错的功能点:

u HTML 5地理定位

u 重力感应滚动

u 滚动Touch事件

u 为移动优化的表单元素

u JSONP代理(跨域数据读取)

u YQL数据代理(类似查询语言式数据获取)

u 遮罩弹出层

u Multi-Card布局

u CSS3 Transitions

u Tab组件以及滚动列表视图

第三章 SenchaTouch第一个例子
3.1 发环境的搭建与调试工具

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

3.2 第一例子

按我们的通用平台架构,视图层使用了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方法来参加一个senchatouch应用页面,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 页面,该方法可以为我们的应用设置不同的启动属性和行为:

l icon,设置该应用默认的图标;

l tabletStartupScreen,该属性设置在平板电脑上的启动图标;

l phoneStartupScreen,该属性设置在智能手机上的启动图标;

l glossOnIcon,该属性设置是否在默认图标上呈现光环效果;

l onReady,该方法会在页面加载完毕,浏览器中的 DOM 模型已经建立完成时被调用。由于为了保证程序在运行时所依赖的JavaScript 文件都已经加载完毕,我们一般将应用启动的逻辑置于该方法内,类似于 Java 程序的 main 方法。

在onReady方法中,有一个地方我们需用注意的:

l Ext.Panel对象的dockedItems属性,通过它可以在panel中放置工具栏等组件,可选值有:top-上,bottom-下,left-左,right-右。fullscreen属性为true(默认为false)则强制该panel充满整个屏幕。monitorOrientation属性为true则可以让panel面板监听屏幕方向发生变化时候的事件。

l 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的方法只会运行一次。

第四章 SenchaTouch布局介绍
在我们的Web应用开发中,页面的排版、布局很重要,用户就是通过页面操作来完成日常工作的。如果界面布局不合理、操作不方便,用户也不会对系统有好的印象、甚至有可能影响一个项目的成败。我自己的经验是,在开发某个功能模块时,除了仔细属性该模块的功能需求和业务需求外,还会在草稿纸上简单的把该功能的布局画出来(如果美工已经制作有页面模型外)。例如:

Sencha Touch的布局类似Extjs中的布局,常用的有:BoxLayout、HBoxLayout、VBoxLayout、FitLayout、CardLayout。

4.1 BoxLayout、HBoxLayout、VBoxLayout(箱子布局)

BoxLayout是箱子布局,该布局类似于药店里放置中草药的大柜子里一个个小箱子那样,把组件放置在容器中(Container)中。BoxLayout是HBoxLayout和VBoxLayout这两个布局类的父类,一般很少直接使用。

u 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

}]

}]

});

有两个属性需要关注一下:

l align: 'stretch',该属性是设置容器里‘小容器’的对齐方式。

l flex属性是设置‘小容器’的宽度比率,具体的计算方式请参看文档。

当然还有其他的属性,例如:style、margin、padding,这些属性主要是设置样式的。

u 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

}]

}]

});

4.2 FitLayout(自适应布局)

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>'

}]

});

4.3 CardLayout(卡片式布局)

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');

};

};

第五章 SenchaTouch表单
用户与系统的交互,绝大部分是通过表单来进行。Sencha Touch的表单与Extjs的表单类似,只是新增了一些html5的元素,例如:url输入框、email输入框、search输入框、Number输入框、slider、toggle等。

5.1 表单元素

表单元素有以下这些,其中有很多都是大家所熟悉的,在此就不做多说明,主要是说明一些新的表单元素及其常用属性,其他(包括组件的方法、事件等)的请大家参照api文档:

l 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:标识为必填,只是做一个标识,表单提交时不会做验证。

l Password密码输入框

密码输入框,xtype类型为passwordfield。

l Select下拉框

下拉框组件,xtype类型为selectfield。主要的属性:

displayField:下拉框显示的字段名

valueField:下拉框值的字段名(该字段所指向的值将会被传递到后台)

options:下拉选项对象数组,对象的成员名称必须与displayField和valueField的相一致。需要注意的是当select组件设置了store属性,则本属性的值将被忽略。

store:提供给select组件下拉选项的store对象实例,通过该属性可以实现级联下拉选择。

l DatePicker日期选择

日期选择组件,xtype类型为datepickerfield。主要的属性:

picker:用来创建日期选择器的配置对象或直接使用一个日期选择器实例。例如:

picker: {

yearFrom: 1910, //设置开始年份

cancelButton: '取消', //设置取消按钮上的文字

doneButton: '完成', //设置完成按钮上的文字

slotOrder: ['year', 'month', 'day'] //设置日期选择器上显示年月日的顺序

}

l Checkbox多选框

多选框组件,xtype类型为checkboxfield。

l Radio单选框

单选框组件,xtype类型为radiofield。

l Email电子邮件输入框

邮件输入框组件,xtype类型为emailfield,是文本输入框组件的子类。该组件暂时没有很特别的属性。

l Url超链接输入框

超链接输入框组件,xtype类型为urlfield,是文本输入框组件的子类。该组件暂时没有很特别的属性。

l Slider滑动选择器

滑动选择器组件,xtype类型为sliderfield,该组件可以让用户通过手指横向滑动来选择值。主要的属性:

minValue:slider的最小值。

maxValue:slider的最大值。

increment:每次滑动的增加值,只能为正整数,默认值为1。

注意:该组件的值不会传递到后台,需要手工调用该组件的getValue()方法获取设置的值,并把这个值设置到一个hidden组件中,以传递给后台程序。可以通过该组件的change事件来检测值的变化情况。

l Toggle开关切换器

开关切换器组件,xtype类型为togglefield,该组件是slider组件的子类,它只设置了两个值:0和1。

该组件和slider组件一样,需要手工调用getValue()方法把值设置到一个hidden组件,才能传递给后台程序。

l Number数字输入框

数组输入框组件,xtype类型为numberfield,是文本输入框组件的子类,但只能输入数字(包括负号与小数点)。

l Spinner微调器

微调器组件,xtype类型为spinnerfield,是number组件的子类。主要的属性:

minValue:spinner的最小值。

maxValue:spinner的最大值。

incrementValue:每次点击-/+按钮时,增加的值。

cycle:循环设置项,该属性为true时,如果值已经到达maxValue设置的值,下一次点击则设置为minValue的值。同样,如果已经达到minValue设置的值,下一次点击则设置为maxValue的值。

l Textarea文本输入域

文本输入域组件,xtype类型为textareafield,负责多行文字的输入。

l Search搜索输入框

搜索输入框组件,xtype类型为searchfield,是文本输入框组件的子类。该组件暂时没有很特别的属性。

5.2 表单常用属性与常用方法

1) 常用属性:

l baseParams:Object

发送到后台的可选参数(只有当standardSubmit属性为false时,即标准提交方式时,不会把这个属性的参数值传递到后台程序),该属性的类型为Object,例如:{‘entity.title’:’hello kitty’}。

l dockedItems:Object/Array

放置到formpanel的一个或一系列组件,这些依附组件可以放置在formpanel的上下左右的位置。其典型应用是在panel上放置toolbars或tabbars,该属性的类型为一个对象或一个对象数组。

l standardSubmit:Boolean

是否执行一个标准提交,默认为false(非标准提交),该属性的类型为boolean型。如果需要上传附件,则必须执行标准提交,即该属性设置为true。

l waitTpl: Object

设置一个ajax提交进度的模板,例如:提交后弹出‘正在保存数据,请稍等…’的提示。

l record:Ext.data.Model

该属性为只读属性,加载到form中的model实例,该属性的类型是Ext.data.Model。

2) 常用方法:

u getRecord(): Ext.data.Model

该方法返回当前加载到form中的model实例。

u getValues(Boolean enabled): Object

返回一个包含有全部表单元素及其值的对象,对象的属性与表单元素的name属性一致,对于具有相同name属性的checkbox或radio元素,它的值为一个值数组。参数enabled若为true则只返回哪些disabled属性为false或undefined的元素值,false则返回全部。

u load(Ext.data.Model instance): Ext.form.FormPanel

把一个model实例中的数据加载到对应的form元素中(model实例中的name与form元素中name属性一致)。该方法是loadRecord方法的快捷键。通过该方法,我们可方便的把数据设置到form元素中。

u loadRecord(Ext.data.Model instance) : Ext.form.FormPanel

把一个model实例中的数据加载到对应的form元素中(model实例中的name与form元素中name属性一致)。

u removeAll([Boolean autoDestroy]): Array

该方法可以删除form容器中的全部组件,例如:从新增页面保存后跳转到修改页面,这时需要调用该方法把新增页面的表单及其元素全部删除,否则会出现相同名字和id的表单元素。sencha touch的页面跳转(setActiveItem方法),是隐藏原来的页面的元素,在该页面的最后自动加上后页的html元素。

u reset(): Ext.form.FormPanel

表单重设方法,把表单元素的值设置为表单元素的起始值。

u 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

回调函数的变量访问。

u updateRecord(Ext.data.Model instance, Boolean enabled):Ext.form.FormPanel

把表单元素中的数据更新到model实例中。

5.3 表单数据加载

表单数据加载,可以通过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从后台获取数据的步骤,其他的都与方式一是一样的,在此不多说了。

5.4 表单数据提交

表单数据提交有两种方式:标准提交和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开发移动应用时需要注意一些情况:

u 后台的数据传输要尽量精简,前台js书写需要尽量简洁。

u 界面要尽量精简以及少用图片,要保证应用的流畅,毕竟移动网络的网速远比不上宽带。

u 应用入口尽量要分模块,因为sencha touch整个应用只有一个入口的话,需要引入大量的js文件,这样可能会导致第一个页面的响应速度很慢(js文件需要下载到浏览器)。

u 一些通用功能尽量组件化,提高组件的重用。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐