许多类在使用配置对象创建(实例化)类时都有快捷名称。快捷名称被称为 alias
(别名)(如果类扩展了 Ext.Component,则为 xtype
)。别名/xtype 列在适用类的类名称旁边,以便快速参考。
框架类或其成员可以指定为 private
(私有)或 protected
(受保护)。否则,类/成员为 public
(公共)。Public
、protected
和 private
是访问描述符,用于传达应该如何以及何时使用类或类成员。
Public(公共)类和类成员可供任何其他类或应用程序代码使用,并且在主要产品版本中可以作为稳定和持久的内容依赖。公共类和成员可以通过子类安全地扩展。
Protected(受保护)类成员是稳定的 public
(公共)成员,旨在由拥有类或其子类使用。受保护成员可以通过子类安全地扩展。
Private(私有)类和类成员在框架内部使用,不打算供应用程序开发人员使用。私有类和成员可能会随时更改或从框架中省略,恕不另行通知,并且不应在应用程序逻辑中依赖。
static
(静态)标签。*请参阅下面的静态。下面是一个类成员示例,我们可以对其进行剖析,以展示类成员的语法(在本例中是从 Ext.button.Button 类查看的 lookupComponent 方法)。
让我们看一下成员行的每个部分
lookupComponent
)( item )
)Ext.Component
)。对于除了 undefined
(未定义)以外不返回任何内容的方法,可以省略此项,或者可以显示为由斜杠 /
分隔的多个可能值,表示返回的内容可能取决于方法调用的结果(即,如果 get 方法调用成功,方法可能返回 Component,如果失败则返回 false
(假),这将显示为 Ext.Component/Boolean
)。PROTECTED
(受保护)- 请参阅下面的标志部分)Ext.container.Container
)。如果成员源自当前类,则源类将显示为蓝色链接,如果是从祖先类或混入类继承的,则显示为灰色。view source
(查看源代码))item : Object
(项目:对象))列出。undefined
(未定义)以外的值,则“返回”部分将注释返回的类或对象类型以及描述(示例中为 Ext.Component
)Available since 3.4.0
(自 3.4.0 版本可用)- 示例中未显示)就在成员描述之后Defaults to: false
(默认为:假))API 文档使用许多标志来进一步传达类成员的功能和意图。标签可以用文本标签、缩写或图标表示。
classInstance.method1().method2().etc();
false
(假),则标记为可阻止的事件将不会触发- 表示框架类
- 单例框架类。*有关更多信息,请参阅单例标志
- 组件类型框架类(Ext JS 框架中扩展 Ext.Component 的任何类)
- 表示类、成员或指南在当前查看的版本中是新的
- 表示类型为 config
(配置)的类成员
- 表示类型为 property
(属性)的类成员
- 表示类型为 method
(方法)的类成员
- 表示类型为 event
(事件)的类成员
- 表示类型为 theme variable
(主题变量)的类成员
- 表示类型为 theme mixin
(主题混入)的类成员
- 表示类、成员或指南在当前查看的版本中是新的
在 API 文档页面的类名称正下方是一行按钮,对应于当前类拥有的成员类型。每个按钮显示按类型计数的成员数(此计数会随着过滤器的应用而更新)。单击按钮将导航到该成员部分。将鼠标悬停在成员类型按钮上将显示该类型的所有成员的弹出菜单,以便快速导航。
与类配置选项相关的 Getter 和 Setter 方法将显示在方法部分以及 API 文档和成员类型菜单的配置部分,就在它们工作的配置下方。Getter 和 Setter 方法文档将在配置行中找到,以便于参考。
您的页面历史记录保存在本地存储中,并显示在顶部标题栏下方(使用可用的实际空间)。默认情况下,仅显示的搜索结果是与您当前查看的产品/版本匹配的页面。您可以通过单击历史记录栏右侧的 按钮并选择“全部”单选按钮来展开显示的内容。这将显示所有产品/版本的所有最近页面访问记录在历史记录栏中。
在历史记录配置菜单中,您还将看到最近页面访问的列表。结果按“当前产品/版本”和“全部”单选按钮过滤。单击 按钮将清除历史记录栏以及保存在本地存储中的历史记录。
如果在历史记录配置菜单中选择“全部”,则将启用“在历史记录栏中显示产品详细信息”复选框选项。选中后,每个历史页面的产品/版本将与历史记录栏中的页面名称一起显示。将光标悬停在历史记录栏中的页面名称上也会将产品/版本显示为工具提示。
可以使用页面顶部的搜索字段搜索 API 文档和指南。
在 API 文档页面上,还有一个过滤器输入字段,该字段使用过滤器字符串过滤成员行。除了按字符串过滤外,您还可以按访问级别、继承和只读过滤类成员。这是通过使用页面顶部的复选框完成的。
API 类导航树底部的复选框过滤类列表以包含或排除私有类。
单击空的搜索字段将显示您最近 10 次搜索,以便快速导航。
每个 API 文档页面(JavaScript 原始类型页面除外)都有一个与该类相关的元数据菜单视图。此元数据视图将具有以下一项或多项
Ext.button.Button
类有一个备用类名称 Ext.Button
)。备用类名称通常是为了向后兼容性而维护的。可运行的示例 (Fiddles) 默认在页面上展开。您可以使用代码块左上角的箭头单独折叠和展开示例代码块。您还可以使用页面右上角的切换按钮切换所有示例的折叠状态。切换所有状态将在页面加载之间记住。
类成员默认在页面上折叠。您可以使用成员行左侧的箭头图标或全局使用右上角的展开/折叠全部切换按钮来展开和折叠成员。
在较窄的屏幕或浏览器上查看文档将导致针对较小外形尺寸优化的视图。桌面视图和“移动”视图之间的主要区别在于
可以通过单击 API 文档页面顶部的类名称来查看类源代码。可以通过单击成员行右侧的“view source”(查看源代码)链接来查看类成员的源代码。
当今的移动 Web 应用程序有望在各种设备上工作,从最小的手机到最大的平板电脑。这些设备具有广泛的屏幕分辨率,并且以不同的方式使用。人们倾向于在家外使用手机应用程序来快速收集一些信息或执行某些操作 - 通常在很短的时间内。平板电脑应用程序更可能在更长的时间内使用,通常在家中或其他他们可以长时间坐着的地方。
所有这一切都意味着人们期望在不同的设备上获得不同的应用程序体验。但是,您的大部分应用程序逻辑和资产可以在不同的体验之间共享。为每个平台编写单独的应用程序既耗时又容易出错,而且很无聊。值得庆幸的是,设备配置文件为我们提供了一种简单的方法,可以在设备类型之间共享尽可能多的代码,同时可以轻松地为每个设备自定义行为、外观和工作流程。
设备配置文件存在于 Application(应用程序)的上下文中,例如,如果我们想创建一个带有手机和平板电脑配置文件的电子邮件应用程序,我们可以定义我们的 app.js,如以下代码示例所示(如果不熟悉,请参阅 Intro to Apps guide(应用程序入门指南))
Ext.application({
name: 'Mail',
profiles: ['Phone', 'Tablet']
});
由于我们没有给我们的 Application(应用程序)一个 launch function(启动函数),目前它只会加载这两个配置文件。按照惯例,它希望在 app/profile/Phone.js 和 app/profile/Tablet.js 中找到它们。以下代码显示了 Phone(手机)配置文件
Ext.define('Mail.profile.Phone', {
extend: 'Ext.app.Profile',
config: {
name: 'Phone',
views: ['Main']
},
isActive: function() {
return Ext.os.is('Phone');
}
});
Tablet(平板电脑)配置文件遵循相同的模式。在 Phone(手机)配置文件中,我们只提供了三个信息 - Profile(配置文件)name(名称)、可选的附加 views(视图)集合,以便在此 Profile(配置文件)激活时加载,以及一个 isActive(是否活动)函数。
isActive(是否活动)函数确定给定的配置文件是否应在您的应用程序运行的设备上处于活动状态。到目前为止,最常见的方法是为 Phone(手机)和 Tablet(平板电脑)创建配置文件,使用内置的 Ext.os.is
方法(例如 Ext.os.is(Phone
(手机)))。您可以在 isActive
(是否活动)函数中编写任何您喜欢的代码,只要它始终为在其上运行的设备返回 true
(真)或 false
(假)即可。
加载配置文件后,将依次调用其 isActive(是否活动)函数。第一个返回 true(真)的配置文件是 Application(应用程序)启动时使用的配置文件。然后,此配置文件设置为 Application(应用程序)的 currentProfile(当前配置文件),并且 Application(应用程序)准备加载其所有依赖项 - 构成应用程序的模型、视图、控制器和其他类。它通过将其自身的依赖项与活动配置文件中指定的依赖项相结合来实现这一点。
例如,让我们修改我们之前的 Application(应用程序),以便它加载自己的模型和视图
Ext.application({
name: 'Mail',
profiles: ['Phone', 'Tablet'],
models: ['User'],
views: ['Navigation', 'Login']
});
最后,当我们在手机上加载应用程序时,Phone(手机)配置文件被激活,应用程序加载以下文件
前三个项目在 Application(应用程序)本身中指定 - User(用户)模型以及 Navigation(导航)和 Login(登录)视图。第四个项目由 Phone Profile(手机配置文件)指定,并遵循特殊形式。按照惯例,特定于 Profile(配置文件)的类应在与 Profile(配置文件)同名的子目录中定义。例如,Phone Profile(手机配置文件)中指定的 'Main'(主)视图从 app/view/phone/Main.js 加载,而如果我们在 Application(应用程序)中定义了 'Main'(主),则它将从 app/view/Main.js 加载。
这同样适用于在 Profile(配置文件)中加载的所有模型、视图、控制器和存储。这很重要,因为它使您能够轻松地在配置文件之间共享行为、视图逻辑等(请参阅下面的专门化视图和控制器部分)。如果您需要加载不符合此约定的类,您可以指定完整的类名
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');
}
});
从此示例中可以看出,您可以混合和匹配完全限定的类名(例如 *'Mail.view.SomeView'*)和相对指定的类名(例如 *'Main'*(主),它变为 *'Mail.view.phone.Main'*)。请注意,为 Profile(配置文件)指定的所有模型、视图、控制器和存储都以这种方式处理。这意味着如果有些模型或存储您只想为平板电脑加载,但不想创建像 *Mail.model.tablet.User* 这样的类,则应指定完全限定的类名(例如,在本例中为 *Mail.model.User*)。
使用配置文件的启动过程与不使用配置文件的启动过程几乎完全相同。基于配置文件的应用程序具有 3 个阶段的启动过程;加载所有依赖项后,会发生以下情况
使用配置文件时,通常使用 Profile(配置文件)launch(启动)函数来创建应用程序的初始 UI。在许多情况下,这意味着 Application(应用程序)的 launch(启动)函数被完全删除,因为初始 UI 通常在每个 Profile(配置文件)中都不同(您仍然可以指定一个应用程序范围的 launch(启动)函数来设置分析或其他与配置文件无关的设置等项目)。
典型的 Profile(配置文件)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');
}
});
请注意,Profile(配置文件)和 Application(应用程序)launch(启动)函数都是可选的 - 如果您未定义它们,则不会调用它们。
Profile(配置文件)实现的大多数专门化发生在视图和控制器中。让我们假设我们有以下平板电脑 Profile(配置文件)
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 照常加载。以下代码示例是 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) 和一个 Profile(配置文件)特定的子类 (Mail.view.tablet.Main),它可以自定义超类的任何方面。在本例中,我们在子类中将 Main(主)视图的标题从“Generic version”(通用版本)更改为“Tablet-specific version”(平板电脑特定版本),因此这是我们在应用程序加载时看到的。
由于这些是普通的类,因此可以使用灵活的配置系统轻松自定义超类的几乎任何部分。例如,假设我们也有一个手机版本的应用程序,我们可以按如下方式自定义其 Main(主)视图的版本(*app/view/phone/Main.js*)
Ext.define('Mail.view.phone.Main', {
extend: 'Mail.view.Main',
config: {
title: 'Phone-specific version',
items: [
{
xtype: 'button',
text: 'This is a phone...'
}
]
}
});
虽然前面的示例很有用,但更常见的是共享视图的某些部分,并将它们以不同的方式拼接在一起以用于不同的配置文件。例如,想象一个电子邮件应用程序,其中平板电脑 UI 是一个分屏,左侧是消息列表,右侧是加载的当前消息。Phone(手机)版本是完全相同的消息列表和一个类似的消息视图,但这次是在 card layout(卡片布局)中,因为没有足够的屏幕空间同时显示两个视图。
为了实现这一点,我们必须创建两个共享的子视图 - 消息列表和消息查看器。在每种情况下,为了简洁起见,我们都省略了类配置
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...
});
最终,为了实现包含两个视图的目标布局,平板电脑 Main(主)视图可能使用以下代码
Ext.define('Mail.view.tablet.Main', {
extend: 'Ext.Container',
config: {
layout: 'fit',
items: [
{
xtype: 'messagelist',
width: 200,
docked: 'left'
},
{
xtype: 'messageviewer'
}
]
}
});
这会在左侧创建一个 200px 宽的消息列表,并使用设备屏幕空间的其余部分来显示消息查看器。现在让我们假设我们想要实现 Phone(手机)布局
Ext.define('Mail.view.phone.Main', {
extend: 'Ext.Container',
config: {
layout: 'card',
items: [
{
xtype: 'messagelist'
},
{
xtype: 'messageviewer'
}
]
}
});
在这种情况下,我们使用带有 card layout(卡片布局)的 Container(容器)(一种一次只显示一个项目的布局),并将列表和查看器都放入其中。在这种情况下,我们仍然需要添加一些逻辑,告诉 Container(容器)在点击列表中的消息时显示消息查看器,但我们已经轻松地在基于当前加载的 Profile(配置文件)的不同配置中重用了我们的两个子视图。
与之前的示例类似,我们可以选择为每个 Profile(配置文件)自定义两个共享视图 - 例如,我们可以创建 Mail.view.phone.MessageViewer 和 Mail.view.tablet.MessageViewer 子类,这两个子类都扩展了 Mail.view.MessageViewer 超类。这使我们能够再次在这些类之间共享大量视图代码,同时呈现适合实际使用的设备的自定义。
与视图类似,许多应用程序都有一些控制器逻辑可以在多个配置文件之间共享。在配置文件的情况下,最重要的区别通常与工作流程相关。例如,应用程序的平板电脑配置文件可能允许您在一个页面上完成工作流程,而手机配置文件则呈现一个多页向导。
在以下示例中,我们有一个简单的 Phone Profile(手机配置文件),它加载一个名为 Main(主)的视图和一个名为 Messages(消息)的控制器。与之前一样,此应用程序加载 app/view/phone/Main.js 和 app/controller/phone/Messages.js
Ext.define('Mail.profile.Phone', {
extend: 'Ext.app.Profile',
config: {
views: ['Main'],
controllers: ['Messages']
},
launch: function() {
Ext.create('Mail.view.phone.Main');
}
});
由于我们已经知道我们的手机和平板电脑特定控制器共享其大部分功能,因此我们在 app/controller/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);
}
});
前一个示例中的 Controller(控制器)执行三个操作
itemtap
(项目点击)事件,并在触发 itemtap
(项目点击)时调用 loadMessage()
函数。loadMessage()
时,将选定的消息项加载到 Viewer(查看器)中。我们现在可以按如下方式创建特定于手机的 Controller(控制器)
Ext.define('Mail.controller.phone.Messages', {
extend: 'Mail.controller.Messages',
config: {
refs: {
main: '#mainPanel'
}
},
loadMessage: function(item) {
this.callParent(arguments);
this.getMain().setActiveItem(1);
}
});
此代码扩展了 Messages(消息)超类控制器,并提供以下功能
loadMessage
函数以执行原始逻辑,然后将主面板的活动项设置为消息查看器。整个超类配置由扩展它的子类继承。在 refs(引用)等重复配置的情况下,配置会合并,因此手机 Messages(消息)控制器类有三个 refs(引用)- main(主)、viewer(查看器)和 messageList(消息列表)。与任何扩展另一个类的类一样,我们可以使用 callParent
来扩展超类中的现有函数。
请记住,*Mail.controller.Messages* 超类未被 Application(应用程序)或 Profile(配置文件)声明为依赖项。它是自动加载的,因为我们的 *Mail.controller.phone.Messages* 控制器扩展了它。
在前面的示例中,我们能够共享一些(但不是全部)我们的 refs(引用)。我们还能够通过使用 Controller(控制器)的 control(控制)配置来共享我们监听的单个事件。一般来说,应用程序在配置文件之间差异越大,您可以共享的 refs(引用)和 control(控制)配置就越少。
应该在不同配置文件之间共享的一个控制器配置是 routes。这些配置将 URL 映射到控制器操作,并提供后退按钮支持和深度链接。将 `routes` 配置保留在超类中非常重要,因为相同的 URL 应该映射到相同的内容,无论设备类型如何。
例如,如果朋友正在使用您应用的手机版本,并向您发送她当前所在应用页面的链接,您应该能够在平板电脑设备上点击该链接,并看到针对该 URL 的平板电脑特定视图。将所有路由保留在超类中使您能够保持一致的 URL 结构,无论设备类型如何都能正常工作。
模型相对于控制器和视图而言,按配置文件进行自定义的频率较低,因此通常不需要子类。在这种情况下,我们仅指定模型的完全限定类名
Ext.define('Mail.profile.Tablet', {
extend: 'Ext.app.Profile',
config: {
models: ['Mail.model.Group']
}
});