当今社会移动设备各式各样,从手机到平板,大小尺寸也各不相同。人们每天耗在移动设备上的时间也越来越多。
这一切都意味着,人们期望在不同的设备上对同一个应用程序有不同的体验。然而,许多应用程序逻辑和资产是可以在不同的体验上共享的。为每个平台编写独立的应用程序是耗时,容易出错,平淡乏味。值得庆幸的是,设备配置文件给我们一个简单的方式来共享之间的设备类型所需的代码,而使它很容易定制外观,行为,并为每个设备配置工作流程。
设置配置文件
设备配置文件存在于应用程序的上下文中,例如,如果我们想创造的手机和平板电脑的配置文件的电子邮件应用程序,我们可以定义我们app.js在下面的代码示例所示(这些代码都可以再Sencha Cmd 创建的工程里看到类似的,可以去准备篇里找相关连接):
Ext.application({
name: 'Mail',
profiles: ['Phone', 'Tablet']
});
这里的例子我们没有给我们的项目一个启动方法(launch)。但是这里去加载了两个配置文件,根据惯例,它去找app/profile/Phone.js 和app/profile/Tablet.js这两个文件。下面的代码是Phone.js中的内容:
Ext.define('Mail.profile.Phone', {
extend: 'Ext.app.Profile',
config: {
name: 'Phone',
views: ['Main']
},
isActive: function() {
return Ext.os.is('Phone');
}
});
Tablet.js中的内容与上面相似。
以上的配置我们只需要补充三个地方,配置文件名name:,启动时加载的视图views:,还有isActive方法。
这个isActive方法决定了你的设备运行App时执行的活动。
关于views,在入口文件中也可以配置,不过这里配置的是公用的:
Ext.application({
name: 'Mail',
profiles: ['Phone', 'Tablet'],
models: ['User'],
views: ['Navigation', 'Login']
});
如果是用手机浏览的,application 加载了一下的文件
app/model/User.js
app/view/Navigation.js
app/view/Login.js
app/view/phone的地址/Main.js
在来个例子:
Ext.define('Mail.profile.Phone', {
extend: 'Ext.app.Profile',
config: {
name: 'Phone',
views: ['Main', 'Mail.view.SpecialView'],
models: ['Mail.model.Message']
},
isActive: function() {
return Ext.os.is('Phone');
}
});
在这个例子中你可以混合使用 类的全名或者简写,models, views, controllers, stores 都可以这样对待。但是如果你不想创建类mail.model.phone.user,你应该指定完全的类名(如mail.model.user),而不是user,因为在phone的配置文件中写成user它会当成mail.model.phone.user。
启动过程
使用了配置文件的工程和没有使用配置文件的启动过程基本上是一样的。
- 控制器被实例化,执行控制器的初始化函数
- 配置文件的launch被调用
- Application的launch被调用
当使用配置文件的情况下,一般Application中的launch方法会被完全移除。
一个典型的配置文件 launch方法可能是以下示例的样子:
Ext.define('Mail.profile.Phone', {
extend: 'Ext.app.Profile',
config: {
name: 'Phone',
views: ['Main']
},
isActive: function() {
return Ext.os.is('Phone');
},
launch: function() {
Ext.create('Mail.view.phone.Main');
}
});
注意:配置文件和Application的launch 方法是可选的,如果你不去定义它们,那就不会被调用。
视图(views)
大部分App的轮廓都是定义在视图和控制器的,下面我们在平板上做个例子:
Ext.define('Mail.profile.Tablet', {
extend: 'Ext.app.Profile',
config: {
views: ['Main']
},
launch: function() {
Ext.create('Mail.view.tablet.Main');
}
});
当我们的程序运行在平板上的时候,根据上面代码会加载到app/views/tablet/Main.js这个文件
Ext.define('Mail.view.tablet.Main', {
extend: 'Mail.view.Main',
config: {
title: 'Tablet-specific version'
}
});
通常,当我们定义一个视图类,我们继承一个Sencha Touch内置的视图,但在前面的例子中,我们继承了一个我们自己定义的视图类mail.view.main。下面的代码示例说明mail.view.main:
Ext.define('Mail.view.Main', {
extend: 'Ext.Panel',
config: {
title: 'Generic version',
html: 'This is the main screen'
}
});
我们再写继承自Mail.view.Main’一个phone的子类:
Ext.define('Mail.view.phone.Main', {
extend: 'Mail.view.Main',
config: {
title: 'Phone-specific version',
items: [
{
xtype: 'button',
text: 'This is a phone...'
}
]
}
});
控制器(Controllers)
假如我们有两个组件,在平板上左右显示,但是手机上显示不下,只能cards的布局显示
//邮件列表
Ext.define('Mail.view.MessageList', {
extend: 'Ext.List',
xtype: 'messagelist'
// config goes here...
});
//邮件内容视图
Ext.define('Mail.view.MessageViewer', {
extend: 'Ext.Panel',
xtype: 'messageviewer'
// config goes here...
});
然后我们可以通过控制器来分配
Ext.define('Mail.profile.Phone', {
extend: 'Ext.app.Profile',
config: {
views: ['Main'],
controllers: ['Messages']
},
launch: function() {
Ext.create('Mail.view.phone.Main');
}
});
上面的例子加载 app/view/phone/Main.js和app/controller/phone/Messages.js:
以手机上显示的为例:
Ext.define('Mail.controller.Messages', {
extend: 'Ext.app.Controller',
config: {
refs: {
viewer: 'messageviewer',
messageList: 'messagelist'
},
control: {
messageList: {
itemtap: 'loadMessage'
}
}
},
loadMessage: function(item) {
this.getViewer().load(item);
}
});
控制器执行操作有三点:
- 建立需要的views
- 监听itemtap事件 执行loadMessage()
当调用 loadMessage() 时加载选择的对象到视图 中
现在我们再来创建一个针对手机的控制器
Ext.define('Mail.controller.phone.Messages', {
extend: 'Mail.controller.Messages',
config: {
refs: {
main: '#mainPanel'
}
},
loadMessage: function(item) {
this.callParent(arguments);
this.getMain().setActiveItem(1);
}
});
Models
模型定制的配置文件比控制器和视图的少,因此通常不需要子类。在这种情况下,我们只指定完全限定类名为模型:
Ext.define('Mail.profile.Tablet', {
extend: 'Ext.app.Profile',
config: {
models: ['Mail.model.Group']
}
});