每个 controller(控制器)都是 Ext.app.Controller 的一个子类,加载它的应用程序也只会对它实例化一次,应用程序自己会控制每个 controller(控制器)在同一时间只有一个实例。我们使用 Application 对象的 controllers 参数来加载 Controller(控制器)并且会自动实例化它们。
A simple example 一个简单例子
Here's how we might quickly define the Sessions controller described above. We're using 2 Controller configurations here - refs and control. Refs are an easy way to find Components on your page - in this case the Controller will look for all Components that match
the formpanel xtype and assign the first one it finds to the loginForm property. We'll use that property in the doLogin function later.
这里将演示如何快速定义上面描述的 Sessions 控制器,我们将使用 controller 的两个配置参数,refs 和 control ,refs 是找到页面组件的简单方式,这个例子里 controller(控制器)会搜索所有 formpanel 类型的控件,然后将找到的第一个赋值给 loginForm 属性,这个属性会在下面的 doLogin 方法中用到。
The second thing it does is set up a control configuration. Just like refs, this uses a ComponentQuery selector to find all formpanel xtypes that contain a button inside them (for example, this will find the Submit button in our hypothetical login form). Whenever any button of this type fires its tap event, our Controller's doLogin function will be called:
然后我们要做的是配置 control 参数,像 refs 一样使用 ComponentQuery 选择器来查找所有包含 button 控件的 formpanel 下的 button 控件,在本例中,将会得到我们登陆表单当中的提交按钮,任意一个符合此条件的 button 触发了tap事件,controller(控制器)都会去调用其中的 doLogin 函数。
Ext.define('MyApp.controller.Sessions', { extend: 'Ext.app.Controller', config: { refs: {
loginForm: 'formpanel' },
control: {
'formpanel button': { tap: 'doLogin' } }
},
doLogin: function() {
var form = this.getLoginForm(), values = form.getValues(); MyApp.authenticate(values);
} });
The doLogin function itself is quite straightforward. Because we defined a 'loginForm' ref, the Controller automatically generates agetLoginForm function that returns the formpanel that it matches. Once we have that form reference we just pull the values (username and password) out of it and pass them to an authenticate function. That's most of what Controllers ever do - listen for events fired (usually by the UI) and kick off some action - in this case authenticating. doLogin 函数本身非常容易理解,由于我们前面定义了一个叫做 loginForm 的 ref ,controller(控制器)将会自动生成一个叫做 getLoginForm 的函数用来返回该 formpanel (也就是这个叫做 loginForm 的 ref 啦),待完成对这个 form 的引用之后,我们只需要把其中的值(用户名和密码)取出来然后传递给 authenticate(身份验证)函数即可,上述就是一个 controller(控制器)能做的绝大部分事情了 —— 侦听事件(通常由UI触发)然后做点别的什么事情,比如用户身份验证。
For more on what Controllers are and what capabilities they possess see the controllers guide.
想了解更多关于 controller(控制器)是什么和能做什么的知识,请查看 controllers guide (控制器指南)页面。
Stores 数据存储器
Stores are an important part of Sencha Touch and power most of the data-bound widgets. At its simplest, a Store is not much more than an array of Model instances. Data-bound Components like List and DataView just render one item for each Model instance in the Store. As Model instances are added or removed from the Store events are fired, which the data-bound Components listen to and use to update themselves.
Store(数据存储器)是 ST 的重要组成部分,它能够实现大部分的组件数据绑定工作。简单来说,一个 store(数据存储器)就是一个由 Model(数据模型)的实例组成的数组,诸如 List 和 DataView 这类的数据绑定型控件,他们会为 Store(数据存储器)中的每一个 Model(数据模型)实例渲染一个 item(这里指数据绑定控件的子项),Store(数据存储器)中的 Model(数据模型)实例被添加或者删除的时候会触发数据绑定控件的相应事件,从而实现控件的更新。
While the Stores guide has much more information on what Stores are and how they fit in with Components in your app, there are a couple of specific integration points with your Application instance that you should be aware of.
Stores guide (数据存储器指南)网页上有更多信息,比如到底什么是 Store(数据存储器)以及它们在你的应用程序中是如何去与 Component(组件)协调工作的,那里还有几个你必须注意的特殊要点,均与 Application 实例有关。
Device Profiles 设备配置文件
Sencha Touch operates across a wide range of devices with differing capabilities and screen sizes. A user interface that works well on a tablet may not work very well on a phone and vice versa so it makes sense to provide customized views for different device types. However, we don't want to have to write our application multiple times just to provide a different UI - we'd like to share as much code as possible.
ST 可以跨越非常广泛的平台,尽管这些平台拥有不同的性能和屏幕尺寸。一个在平板电脑上工作良好的UI并不一定适应手机界面,反之亦然。所以为不同设备提供定制过的不同 view(视图)是一件很有必要的事情。毕竟谁也不想仅仅为了提供不同的 UI 就得把应用程序重写 N 次,我们希望可以让不同设备共享尽可能多的代码。
Device Profiles are simple classes that enable you to define the different types of devices supported by your app and how they should be handled differently. They are opt-in, so you can develop your app without profiles at first and add them in later, or never use them at all.Each profile simply defines an isActive function that should return true if that profile should be active on the current device, plus a set of additionalmodels, views and controllers to load if that profile is detected.
Device Profile(设备配置)是一些简单的类,这些类能让你定义程序支持的不同类型设备以及如何处理这些不同。Device Profile(设备配置)不是必需的,你可以一开始不定义Profile 以后再添加,甚至永远不定义它们。每个 profile 都要定义一个简单的 isActive 函数,用来返回当前设备上是否应该启用此 profile(换言之,该 profile 是否匹配当前的设备) ,并为该 profile 载入一堆(当前 profile 中约定的)model ,view 和 controller 。
To app Profile support to your app you just need to tell your Application about those Profiles and then create Ext.app.Profile subclasses for them:
要为你的应用程序添加 Profile 支持功能(怀疑英文原文第一个 app 应为 add ),你只需告诉应用程序有哪些 profile 需要被支持,然后为它们各自创建Ext.app.Profile 的子类即可。
Ext.application({ name: 'MyApp',
profiles: ['Phone', 'Tablet'],
//as before });
By defining the profiles above the Application will load app/profile/Phone.js and
app/profile/Tablet.js. Let's say that the tablet version of the app enables additional capabilities - for example managing groups. Here's an example of how we might define the Tablet profile: 如上面代码所示,应用程序会加载 app/profile/Phone.js 和 app/profile/Tablet.js 两个文件,我们假定平板电脑的版本将会拥有一些额外的能力,比如对组的管理功能,下面的例子将告诉我们该如何定义tablet的profile:
Ext.define('MyApp.profile.Tablet', { extend: 'Ext.app.Profile',
config: {
controllers: ['Groups'], views: ['GroupAdmin'],
models: ['MyApp.model.Group']
},
isActive: function() { return Ext.os.is.Tablet; } });
The isActive function will return true whenever the application is run on what Sencha Touch
determines to be a tablet. This is a slightly subjective determination because there is a
near-continuous spectrum of device shapes and sizes with no clear cutoff between phones and tablets. Because there is no foolproof way to state which devices are tablets and which are phones, Sencha Touch's Ext.os.is.Tablet is set to true when running on an iPad and false otherwise. If you need more fine grained control it's easy to provide any implementation you like inside your isActive function, so long as it returns true or false.
当ST检测到你的设备是一台平板电脑时,isActive 函数将会返回 true 。鉴于现在不断涌现出的各种新设备,其外形和尺寸已经越来越模糊了手机和平板电脑的界限,故而我们无法找到傻瓜化的方式去界定哪些设备是平板哪些设备是手机,ST 的 Ext.os.is.Tablet 只有在 iPad 上运行的时候将被设定为 true ,其他则为 false ,如果你需要更好的判断和控制,你可以通过在 isActive 函数中进行更多你希望的检测,来控制它返回 true 还是 false 。
You should make sure that only one of your Profiles returns true from its isActive function. If more than one of them returns true, only the first one that does so will be counted and the rest ignored. The first one that returns true will be set as the Application's currentProfile, which can be queried at any time.
你必须保证只有一个 profile 的 isActive 函数可以返回 true ,如果超过一个的话,只有第一个会有效而其他将被忽略,第一个返回 true 的 profile 将被视作应用程序的 currentProfile(当前 profile ),你也可以随时获取到当前 profile 的值。
If the detected currentProfile has defined additional models, views, controllers and stores these will be automatically loaded by the Application, along with all of
the models, views and controllers defined on the Application itself. However, all of the dependencies named in the Profile will be prepended with the Profile name unless the fully-qualified class name is provided. For example:
如果检测到的当前profile定义了额外的 model(数据模型)、view(视图)、controller(控制器)、store(数据存储器),它们会与 application 当中定义的其他元素一起被自动加载。而所有在 profile 中定义的元素路径前面都会被加上 profile 的名称,除非你对它们定义了完整路径的类名,如下所示。
?
views: ['GroupAdmin'] will load app/view/tablet/GroupAdmin.js
views: ['GroupAdmin'] 将会加载 app/view/tablet/GroupAdmin.js (因为 GroupAdmin 是在 tablet profile 中配置的)
? controllers: ['Groups'] will load app/controller/tablet/Groups.js
controllers: ['Groups'] 将会加载 app/controller/tablet/Groups.js (同上)
? models: ['MyApp.model.Group'] will load app/model/Group.js
models: ['MyApp.model.Group'] 将会加载 app/model/Group.js (因为使用了完整路径)
Most of the time a Profile will only define additional controllers and views as the models and stores are typically shared between all variants of the app. For a more detailed discussion of Profiles see the device profiles guide.
绝大多数情况下,profile 只会定义额外的 controller 和 view ,因为 model 和 store 一般情况下都会被共享。关于 profile 的更多细节,请访问 device profiles guide 页面(设备配置指南)。
Launch Process Application的Launch