原文标题:Getting Started with Sencha Touch 2: Build a Weather Utility App (Part 1)
原文地址:http://www.sencha.com/blog/getting-started-with-sencha-touch-2-build-a-weather-utility-app-part-1/
作者:Lee Boonstra
Lee is a technical trainer at Sencha. She’s located in Amsterdam and has experience in both front-end and back-end development. Lee spends her spare time developing web and mobile apps. She is writing a cookbook for O'Reilly about Sencha Touch.
在这三个部分的Sencha Touch教程中,将会创建一个简单的我是否需要带伞的实用应用程序,它会从worldweatheronline.com提供的Web服务中加载天气信息。基于天气代码,该应用程序可以预测需要不需要带伞。
在本教程,需要为应用程序编写代码。在下一个教程,重点是创建酷的Sencha Touch主题和如何使用PhoneGap将应用程序转为本地应用程序。
本教程有以下要求:
Sencha Touch 2.3或更高版本
Sencha Cmd 4.x
一个现代浏览器
编辑器
以下是一些附加资源:
可以在这里查看该应用程序并运行它。
最终代码可以在这里下载。
有一些教程所需的好东西――控制器和功能
首先要做的是在硬盘上创建Sencha的文件夹。下载Sencha Touch 2.3并解压到新创建的Sencha文件夹。现在,要为应用程序创建文件夹,我将它命名为dinumu,是“Do I Need My Umbrella”的首字母组合。
现在,在命令行(命令提示符货Mac OS X终端),进入Sencha框架文件夹(cd sencha/touch-2.3.x)并运行以下命令来生成Sencha Touch MVC的目录结构:
sencha generate app -name Dinmu -path ../dinmu
以上命令会为应用程序“我需要带伞么”生成完整的MVC结构。它的命名空间为Dinmu,是所有类的前缀。检查一下已创建的目录结构。
现在可以通过命令行来启动Web服务器――使用Sencha文件夹作为路径。(如果想使用已有的Apache服务器,可以跳过这个步骤。)在Mac OS X,可能需要权限来执行以下命令:如果运行的时候出现权限错误,需要在命令前加上前缀sudo。
sencha fs web -p 80 start -map /path/to/sencha/folder/
下面来测试生成的Sencha Touch应用程序。打开现代浏览器(如Google Chrome货Safari)并输入:http://localhost/dinmu,将会看到下图所示的Sencha演示应用程序接口,在底部标签面板带有两个演示页:
下一步要做的是生成模型来定义数据。在应用程序中需要保存的设置包括:id、city(城市)、country(国家)、units(单位)和geolocation(地理定位)。这些数据将会作为模型的字段来进行定义。Sencha Cmd可以用来搭建这个模型。在dinmu文件夹内,运行以下命令:
sencha generate model Setting id,city,country,units,geo:boolean
在编辑器中打开app/model/Setting.js。要注意Dinmu.model.Setting相当于app/model/Setting.js。这就是要实现的Setting模型,Sencha Cmd会去定义一个Setting模型类。它派生于Sencha Touch框架的模型实现Ext.data.Model,且包含了所有的字段和字段类型。
字段id将作为应用程序中每一个模型记录的标识。为了让它表现为唯一的id值,需要去配置它。在fields数组前,添加配置项idProperty和identifier。
idProperty: 'id',
identifier: 'uuid',
requires: ['Ext.data.identifier.Uuid'],
validations: [{
type: 'presence',
field: 'city',
message: "Please provide a city."
}, {
type: 'presence',
field: 'country',
message: "Please provide a country."
}
],
proxy: {
type: 'localstorage',
id: 'weathersettings'
}
Sencha Cmd生成的的标准的标签面板界面看上去不错,但这并适合任何应用程序。“我需要带伞么”应用程序需要需要的是滑动(carousel )界面。
在IDE或文本编辑器,打开app/view/Main.js文件。
当前的Dinmu.view.Main实现派生于Sencha Touch的Ext.tab.Panel类,并通过tabBarPosition属性将标签放置到了屏幕底部。
这并不是所需的,所以要将“tabBarPosition:bottom”删除,并将extend的值修改为Ext.Carousel以便从Sencha Touch的Ext.Carousel类派生。现在,,在浏览器打开并运行http://localhost/dinmu,会看到创建的Sencha示例应用程序内,标签页界面已被替换为滑动视图界面,可以通过水平滑动来切换视图。
下面来删除更多的默认组件。在这里,不需要演示视频,因此要在requires数组中删除Ext.Video。还需要清空items数组,这样就可将他们替换为新的子组件。
第一个子组件对象(默认为容器)只有html属性,该属性可以设置为占位符文本:Settings Form(设置表单),以便稍后再编写代码。第二个子组件对象包含属性itemid(值为mainview)和属性cls(值为textview)。还有添加一个direction属性,值为vertical,以便能垂直滑动。
Ext.define('Dinmu.view.Main', {
extend: 'Ext.Carousel',
xtype: 'main',
requires: [
'Ext.TitleBar'
],
config: {
direction: 'vertical',
items: [{
html: 'Settings Form'
},{
itemId: 'mainview',
cls: 'textview'
}]
}
});
{
xtype: 'titlebar',
cls: 'title',
docked: 'top',
title: 'Do I need my Umbrella?'
},
{
xtype: 'toolbar',
cls: 'footer',
ui: 'light',
docked: 'bottom',
html: '<span>Powered by © Sencha Touch</span>'
},
Ext.define('Dinmu.view.Main', {
extend: 'Ext.Carousel',
xtype: 'main',
requires: [
'Ext.TitleBar',
'Ext.Toolbar'
],
config: {
direction: 'vertical',
items: [
{
xtype: 'titlebar',
cls: 'title',
docked: 'top',
title: 'Do I need my Umbrella?',
items: [{
cls: 'back',
hidden: true,
ui: 'back',
action: 'back',
align: 'left',
text: 'back'
},
{
iconCls: 'settings',
action: 'settings',
ui: 'plain',
align: 'right'
}]
},
{
html: 'Settings Form'
},{
itemId: 'mainview',
cls: 'textview'
},
{
xtype: 'toolbar',
cls: 'footer',
ui: 'light',
docked: 'bottom',
html: '<span>Powered by © Sencha Touch</span>'
}]
}
});
现在,开始创建一个表单。你知道吗?这一样可以使用生成的方式来创建。在命令行,切换到dinmu目录并运行以下命令来生成Sencha Touch表单:
sencha generate form SettingsView geo:toggle,units:select,city,country
下面检查以下已经构建好的表单类。打开app/view/SettingsView.js文件,Dinmu.view.SettingsView类的xtype属性被设置为settingsview,这样,就可以在items数组中使用xtype属性来创建类。
现在来实现这个,打开Dinmu.view.Main (app/view/Main.js),在代码中找到设置子组件。默认情况下,如果没有知道xtype属性,将会设置为容器。在这里,需要将xtype属性设置为settingsview,所以要添加“ xtype: ‘settingsview’”到主视图代码。不要忘记将Dinmu.view.SettingsView添加到requires数组以确保该类能加载到内存。
为了让它好看起来更好看,可以在SettingsView的Ext.form.Panel中添加一个字段集(fieldset)。在字段集中,将包含4个新字段和提交按钮。字段集是表单面板(formpane)的子组件,而它的子组件是表单字段和按钮。
要在配置对象内items数组创建第二个items数组(在title属性后)。嵌套的第二个items数组将作为子组件。父的items数组将包含一个xtype属性,值为fieldset,还有title属性,值为“Your Location”(你的位置),以及instructions(说明)属性。
要确保子的items数组包含所有的字段和按钮。最终代码如下:
Ext.define('Dinmu.view.SettingsView', {
extend: 'Ext.form.Panel',
xtype: 'settingsview',
config: {
items:[{
xtype: 'fieldset',
title: 'SettingsView',
instructions: 'In case you do not want the app to detect your location you can enter the city and country.',
items: [
{
name: 'geo',
xtype: 'togglefield',
label: 'Geo'
},
{
name: 'units',
xtype: 'selectfield',
label: 'Units'
},
{
name: 'city',
xtype: 'textfield',
label: 'City'
},
{
name: 'country',
xtype: 'textfield',
label: 'Country'
},
{
xtype: 'button',
text: 'Submit',
ui: 'confirm'
}
]
}]
}
});
{
xtype: 'button',
text: 'Refresh',
action: 'refresh',
margin: '10 5'
ui: 'confirm'
}
requires: [
'Ext.form.FieldSet',
'Ext.field.Toggle',
'Ext.field.Select',
'Ext.field.Text',
'Ext.Button'
],
Ext.define('Dinmu.view.SettingsView', {
extend: 'Ext.form.Panel',
xtype: 'settingsview',
requires: [
'Ext.form.FieldSet',
'Ext.field.Toggle',
'Ext.field.Select',
'Ext.field.Text',
'Ext.Button'
],
config: {
items:[{
xtype: 'fieldset',
title: 'SettingsView',
instructions: 'In case you do not want the app to detect your location you can enter the city and country.',
items: [
{
name: 'geo',
xtype: 'togglefield',
label: 'Auto Detect?',
labelWidth: '55%',
value: '1'
},
{
name: 'units',
xtype: 'selectfield',
options: [
{
text: 'Fahrenheit',
value: 'f'
},
{
text: 'Celsius',
value: 'c'
}],
label: 'Units',
disabled: true
},
{
name: 'city',
xtype: 'textfield',
label: 'City',
disabled: true
},
{
name: 'country',
xtype: 'textfield',
label: 'Country',
disabled: true
},
{
xtype: 'button',
text: 'Refresh',
action: 'refresh',
margin: '10 5',
ui: 'confirm'
}
]
}]
}
});
控制器(controller)可以将设置模型(应用程序的数据)和设置视图粘合起来。它将包含对所以视图组件的引用,并分发事件。切换到dinmu文件夹并运行以下命令:
sencha generate controller Main
refs: {
mainView: 'main',
settingsView: 'settingsview',
btnSettings: 'main button[action=settings]',
btnRefresh: 'settingsview button[action=refresh]',
btnBack: 'main button[action=back]',
toggleGeo: 'settingsview togglefield',
fieldCity: 'settingsview textfield[name=city]',
fieldCountry: 'settingsview textfield[name=country]',
fieldUnits: 'settingsview selectfield'
},
control: {
'btnRefresh': {
tap: 'onRefresh'
},
'btnSettings': {
tap: 'onSettingsBtnTap'
},
'btnBack': {
tap: 'onBackBtnTap'
},
'toggleGeo': {
change: 'onToggle'
},
'mainView': {
activeitemchange: 'onCarouselChange'
}
}
controllers: [
'Main'
],
Store封装了一个模型对象的客户端缓存。Store也可以设置代理并可以为所包含的模型实例(记录)提供排序、过滤、分析和查询等功能。
目前这个应用程序需要一个Store来保存所以用户设置。
很不幸,不可以使用Sencha Cmd来创建Store。下面,在app/store目录下创建一个名为Setting.js的新文件。在文件中,定义一个新类Dinmu.store.Settings,该类派生于Ext.data.Store。在config对象中,添加model属性,连接到Setter模型。此外,还有设置成自动加载。
Ext.define('Dinmu.store.Settings', {
extend: 'Ext.data.Store',
requires: ['Dinmu.model.Setting'],
config: {
model: 'Dinmu.model.Setting',
autoLoad: true
}
});
stores: 'Dinmu.store.Settings',
Ext.define('Dinmu.utils.Functions', {
singleton: true,
//singleton methods here
});