Ext JS提供了对MVC和MVVM应用程序架构的支持。 这两种架构方式分享某些概念和逻辑沿线的关注将应用程序代码。 每种方法都有其优势基础上如何选择分割的应用程序。
本指南的目的是为您提供有关组件,这些基础知识架构。
在MVC体系结构中,大多数类模型、视图和控制器。 用户与之交互视图,显示数据模型。 这些交互监控控制器,然后通过更新响应交互视图和模型,作为必要的。
视图和模型一般都不知道对方因为控制器的唯一责任指导更新。 一般来说,控制器将包含一个MVC应用程序内的大多数应用程序逻辑。 理想的观点很少(如果有的话)的业务逻辑。 数据模型主要是一个接口,包含业务逻辑来管理变化来表示数据。
MVC的目标显然是为应用程序中的每个类定义的责任。 因为每一个类都有明确的责任,他们暗中成为脱离更大的环境。 这使得应用程序更容易测试和维护,和它的代码更加可重用。
MVC和MVVM的关键区别在于MVVM称为ViewModel功能的抽象视图。 ViewModel坐标之间的变化模型的数据和视图的显示数据使用一种称为“数据绑定”的技术。
结果是,模型和框架完成尽可能多的工作,最大限度地减少或消除应用程序逻辑,直接操作视图。
Ext JS 5引入了支持MVVM架构以及在MVC(C)的改进。 虽然我们鼓励您调查和利用这些改进,重要的是要注意,我们已经尽了最大努力以确保现有Ext JS 4 MVC应用程序继续修改的功能。
了解这些选择适合您的应用程序,我们应该首先定义各种缩写代表什么。
(M)模型这是为您的应用程序的数据。 一组类(称为“模型”)定义了字段的数据(如用户模型与用户名和密码字段)。 通过数据模型知道如何坚持自己包,可以通过协会与其他模型。
模型通常用于与商店为电网提供数据和其他组件。 模型也是一个理想的位置为任何你可能需要的数据逻辑,比如验证、转换等。
(V)视图——一个视图是任何类型的组件,是视觉表示。 例如,网格,树木和面板都是考虑的观点。
(C)控制器——控制器作为一个地方维护视图的逻辑,使您的应用程序的工作。 这可能需要渲染视图、路由实例化模型,和任何其他类型的应用程序逻辑。
(VM)视图模型——ViewModel类,管理数据的视图。 它允许组件绑定到它感兴趣和更新这些数据的变化。
这些应用程序架构提供结构和框架代码的一致性。 按照惯例我们建议将提供许多重要的好处:
每个应用程序在相同的方式工作,所以你只需要学一次。
很容易在应用程序之间共享代码。
您可以使用Sencha Cmd创建优化的生产版本的应用程序。
在我们开始之前走过,让我们构建一个示例应用程序Sencha Cmd。 只是发出以下命令从命令行:
sencha generate app -ext MyApp ./app cd app sencha app watch
注意:如果你不熟悉上面发生了什么事,请看看我们入门指南。
在我们开始讨论,MVC,MVVM,MVC +虚拟机模式,让我们看看Cmd生成应用程序的结构。
Ext JS应用程序遵循统一的目录结构,每个应用程序都是相同的。在我们推荐的布局,所有的类都放入app
文件夹中。 这个文件夹包含子文件夹,名称空间模型, 商店和视图元素。 视图元素,如视图,viewcontroller,视图模型应保持组合在一起作为组织的最佳实践(请参阅下面的“主要”视图文件夹)。
每个类的第一行是一个各种各样的地址。 这种“地址”被称为一个名称空间。 名称空间的公式是:
<AppName>.<foldername>.<ClassAndFileName>
在你的示例应用程序,浏览器名称,“MyApp”“视图”文件夹名称,“主要”子文件夹名称和“主要”是阶级和文件名。 基于这些信息,查找一个文件名为框架Main.js
在以下位置:
app/view/main/Main.js
如果没有找到该文件,Ext JS将抛出一个错误,直到你解决这种情况。
让我们开始评估应用程序通过查看index.html
。
<!DOCTYPE HTML> <html> <head> <meta charset="UTF-8"> <title>MyApp</title> <!-- The line below must be kept intact for Sencha Cmd to build your application --> <script id="microloader" type="text/javascript" src="bootstrap.js"></script> </head> <body></body> </html>
Ext JS使用Microloader加载应用程序资源描述的app.json
文件。 这取代了需要添加他们index.html
。 与app.json
所有的应用程序元数据存在于一个位置。Sencha Cmd可以编译你的应用程序在一个简单而有效的方式。
app.json
大量注释,提供了一个极好的资源收集有关信息接受的信息。
当我们生成的应用程序之前,我们创建了一个类(在Application.js
(在)和启动一个实例app.js
)。 你可以看到的内容app.js
下图:
/* * This file is generated and updated by Sencha Cmd. You can edit this file as * needed for your application, but these edits will have to be merged by * Sencha Cmd when upgrading. */ Ext.application({ name: 'MyApp', extend: 'MyApp.Application', autoCreateViewport: 'MyApp.view.main.Main' //------------------------------------------------------------------------- // Most customizations should be made to MyApp.Application. If you need to // customize this file, doing so below this section reduces the likelihood // of merge conflicts when upgrading to new versions of Sencha Cmd. //------------------------------------------------------------------------- });
autoCreateViewport一个新特性是Ext JS的5。 通过指定autoCreateViewport容器类,您可以使用任何类作为你的视窗。 在上面的例子中,我们已经确定MyApp.view.main.Main
(一个容器类)我们的视窗。
的autoCreateViewport配置指示应用程序来创建指定的视图和附加视窗插件。 这个连接视图和文档的身体。
每一个Ext JS应用程序启动的一个实例应用程序类。 这个类的目的是成为launch-ableapp.js
以及instantiable进行测试。
下面的Application.js
内容生成应用程序时自动创建Sencha Cmd。
Ext.define('MyApp.Application', { extend: 'Ext.app.Application', name: 'MyApp', stores: [ // TODO: add global/shared stores here ], launch: function () { // TODO - Launch the application } });
的应用程序类包含全局设置为您的应用程序,比如应用程序的命名空间,共享存储等。
只不过是一个组件,它的一个子类Ext.Component。 一个视图包含所有应用程序的视觉方面。
如果你打开starter应用程序的Main.js
在“主要”文件夹中,您应该看到下面的代码。
Ext.define('MyApp.view.main.Main', { extend: 'Ext.container.Container', xtype: 'app-main', controller: 'main', viewModel: { type: 'main' }, layout: { type: 'border' }, items: [{ xtype: 'panel', bind: { title: '{name}' }, region: 'west', html: '<ul>...</ul>', width: 250, split: true, tbar: [{ text: 'Button', handler: 'onClickButton' }] },{ region: 'center', xtype: 'tabpanel', items:[{ title: 'Tab 1', html: '<h2>Content ...</h2>' }] }] });
请注意,视图不包含任何应用程序逻辑。 你所有的视图的逻辑部分应该包含在它们在下一节中,我们将讨论。
这个特定的视图定义了一个容器边界布局与西方和中心地区。 这些地区包括面板与一个工具栏包含一个按钮和一个选项卡面板用一个选项卡。 如果您不熟悉这些概念,看看我们入门指南。
两个有趣的这个视图控制器和视图模型配置。
控制器配置允许您指定一个它们为视图。 当一个它们以这种方式指定在一个视图,然后它就变成了一个事件处理程序和引用容器。 这就给了它们一个一对一的关系从视图组件和事件。 在下一节中我们将进一步讨论控制器。
viewModel配置允许您指定一个视图模型为视图。 ViewModel是该组件的数据提供者和它的子视图。 通常使用视图模型中包含的数据绑定配置添加到组件想要礼物或编辑这些数据。
在上面的视图中,您可以看到,西部地区的面板的标题是绑定到视图模型。 这意味着标题将被填充数据的“名称”价值,这在ViewModel管理。 如果ViewModel的数据变化,标题的值将自动更新。 我们将在本文的后面讨论视图模型。
接下来,让我们看一看控制器。 ViewController starter应用程序的生成MainController.js
看起来像这样:
Ext.define('MyApp.view.main.MainController', { extend: 'Ext.app.ViewController', requires: [ 'Ext.MessageBox' ], alias: 'controller.main', onClickButton: function () { Ext.Msg.confirm('Confirm', 'Are you sure?', 'onConfirm', this); }, onConfirm: function (choice) { if (choice === 'yes') { // } } });
如果你回顾一下你的观点,Main.js
,你会发现一个函数指定tbar按钮的处理程序。 处理程序映射到一个功能叫做onClickButton控制器。 正如您可以看到的,该控制器已准备好应对该事件没有特殊设置。
这使它非常容易添加为您的应用程序逻辑。 所有你需要做的就是onClickButton函数自定义的视图控制器有一个一对一的关系。
单击视图的按钮时,将创建一个消息框。 这个消息框包含它自己的函数调用onConfirm,作用域相同的控制器。
viewcontroller旨在:
使连接视图使用“听众”和“参考”配置明显。
利用视图来自动管理的生命周期相关ViewController。 从实例化到毁灭,Ext.app。 ViewController与引用它的组件。 第二个实例相同的视图类ViewController会得到自己的实例。 当这些观点被摧毁,他们的相关ViewController实例将被摧毁。
为使嵌套视图直观提供封装。
接下来,让我们看一看视图模型。 如果你打开你的MainModel.js
文件,您应该会看到以下代码:
Ext.define('MyApp.view.main.MainModel', { extend: 'Ext.app.ViewModel', alias: 'viewmodel.main', data: { name: 'MyApp' } //TODO - add data, formulas and/or methods to support your view });
一个视图模型是一个类,管理一个数据对象。 然后这类允许感兴趣数据视图绑定到它和更改的通知。 ViewModel ViewController一样,属于引用它。 因为视图模型与一个视图相关联,他们也可以链接到一个父视图模型由祖先组件的组件层次结构。 这允许子视图只是“继承”的数据父视图模型。
从我们的观点我们创建了一个链接到ViewModel Main.js ViewModel配置。 该链接允许绑定配置的setter从viewModel到自动设置数据视图以声明的方式。 数据是在MainModel内联。 js的例子。 也就是说,您的数据可以是任何东西,来自任何地方。 数据可能会提供的任何形式的代理(AJAX、休息等)。
模型和商店应用程序的信息门户。 大部分数据发送、检索、组织、和“建模”这两个类。
一个Ext.data.Model代表任何类型的persist-able数据在应用程序中。 每个模型都有字段和函数,允许您的应用程序“模型”数据。 模型是最常用的结合。 商店可以使用数据绑定组件,如网格树,和图表。
我们的样例应用程序目前并不包含一个模型让我们添加以下代码:
Ext.define('MyApp.model.User', { extend: 'Ext.data.Model', fields: [ {name: 'name', type: 'string'}, {name: 'age', type: 'int'} ] });
上面所的名称空间部分,您将希望创建User.js
将生活在app /模型。
Ext.data.Model描述记录包含值或属性被称为“字段”。 模型类可以声明这些字段使用“字段”配置。 在这种情况下,宣称是“名字”字符串和年龄是一个整数。 还有其他的字段类型可用的API文档。
尽管有很好的理由宣布字段及其类型,这样做不是必需的。 如果你不包括字段配置,数据会自动读取和插入到数据对象。 如果您想要定义字段数据需求:
验证
默认值
转换函数
让我们建立一个商店,看看这两个一起工作。
一个商店是一个客户端缓存的记录(一个模型类的实例)。 商店提供排序功能,过滤和查询中包含的记录。
这个示例应用程序不包含一个商店,但是不用担心。 简单地定义您的存储和分配模型。
Ext.define('MyApp.store.User', { extend: 'Ext.data.Store', model: 'MyApp.model.User', data : [ {firstName: 'Seth', age: '34'}, {firstName: 'Scott', age: '72'}, {firstName: 'Gary', age: '19'}, {firstName: 'Capybara', age: '208'} ] });
添加上述内容User.js
,应放置在app /商店。
您可以添加存储Application.js
存储的配置如果你想要一个全局实例存储。 的存储配置Application.js
应该像这样:
stores: [ 'User' ],
在本例中,存储直接包含数据。 大多数现实世界的情况下会要求你使用代理收集数据模型或商店。 代理允许数据提供商和应用程序之间的数据传输。
你可以阅读更多关于模型,在我们的商店,和数据提供者数据导。
我们已经创建了一个健壮的和有用的应用程序称为示例应用。 这个应用程序管理登录/注销会话,包含数据绑定,并显示“最佳实践”时,利用MVC + VM架构。 这个例子是说,因此,一切都尽可能明确。
我们建议你花些时间去探索示例应用了解更多关于理想的MVC +虚拟机应用程序体系结构。