您的应用程序架构中的Ext JS 4,第2部分
在先前的Ext JS建筑的文章中,我们探讨了如何构建一个潘多拉风格的应用程序,使用Ext JS的。我们看看在模型 - 视图 - 控制器架构,以及如何将它应用到一个相对复杂的UI应用程序有多个视图和模型。在这篇文章中,我们要超越视觉架构的应用,并探讨如何设计和代码的控制器和模型,与Ext.application的Viewport类开始。
让我们只跳,并开始编写应用程序。
定义我们的应用程序
在Ext JS 3,Ext.onReady方法的入口点到您的应用程序,开发与应用架构。在Ext JS 4,我们有一个引进像一个MVC模式。这种模式可以帮助你创建你的应用程序时遵循的最佳做法。
进入新的MVC包编写的应用程序的入口点,你必须使用Ext.application方法。此方法将创建一个Ext.app.Application为你实例和页是准备尽快将火发射方法。这基本上取代需要使用Ext.onReady,同时增加新的功能,如自动创建一个视口,并设置您的命名空间。
APP / Application.js
分机。应用({
名称: “熊猫” ,
autoCreateViewport : 真实,
推出: () {
/ /这页是准备尽快被激发
} } );
导致要创建一个新的命名空间的名称配置。我们所有的意见,模型,商店和控制器将生活在这个命名空间。该框架通过设置autoCreateViewport为true,将按照惯例,包括在app /视图/ Viewport.js的文件。在这个文件中,一个类应该被定义名称Panda.view.Viewport,相匹配的是您的应用程序的名称配置中指定的命名空间。
“视口类
当我们意见,我们需要我们的UI看,我们非常关注的各个部分。应用程序的视角作为这些单个零件的胶水。它加载所需的看法和定义需要的配置,以实现您的应用程序的整体布局。我们已经发现,逐步确定了你的意见,并将它们添加到视口是最快的方式来创建UI的基础结构。
它是在这个过程中,重要的是集中脚手架上你的意见,而不是自己个人意见。这几乎就像雕刻。我们开始创建我们的意见很粗糙的形状,后来他们增加更多的细节。
创建积木
凭借我们的工作已经做在前面的文章中,我们能够一次定义许多的意见。
APP /视图/ NewStation.js的的
配置...
});
APP /视图/ SongControls.js
分机定义(的“Panda.view.SongControls' , {
延长: “Ext.Container” ,
别名: “widget.songcontrols' ,
...... 更多的配置...
});
APP /视图/ StationsList的的
配置...
});
APP /视图/ RecentlyPlayedScroller.js的的
配置...
});
APP /视图/ SongInfo.js的的
分机定义('Panda.view.SongInfo“ , {
延长: “Ext.panel.Panel” ,
别名: “widget.songinfo ,
TPL : “关于</ H1> <P> </ P> <H1> ,
... 更多的配置...
});
我们已经离开了这里,因为一些配置组件配置在本文的讨论范围。
在上述配置中,你会发现,我们有三家分店配置。这些地图在以前的文章编写的商店名称。在这一点上,我们将继续前进,创造我们的商店。
模型和商店
通常情况下,它是有用的开始与包含模拟数据作为我们的服务器端的静态JSON文件。以后,我们可以使用这些静态文件作为参考,当我们真正实现一个动态的服务器端。
对于我们的应用程序,我们决定使用两种模式,电台和歌曲。我们还需要使用这两种模式将被绑定到我们的数据组件的三家商店。每家商店将它的数据从服务器端加载。模拟数据文件看起来像下面这样。
静态数据
数据/ songs.json
{
'成功' ,
'结果' : [
{
'名称' : '蓝色日出(现场),
“艺术家” : “史蒂维雷沃恩” ,
“相册” : “蓝色日出” ,
“说明” : “史蒂维”的描述,
“played_date' : '1' ,
'站' : 1
},
...
]
}
数据/ stations.json
{
'成功' ,
'结果' : [
{ '身份证' : 1 , “played_date' : 4 '名称' : '齐柏林飞船' },
{ '身份证' : 2 , “played_date : 3 , “名称“ : “滚石” },
{ '身份证' : 3 , “played_date : 2 , “名” : “Daft Punk的” }
]
}
数据/ searchresults.json
{
'成功' ,
'结果' : [
{ '身份证' : 1 , '名称' : '齐柏林飞船' },
{ 'ID' , '名称' : '滚石' },
{ ' : 3 , '名称' : 'Daft Punk的“ },
{ “ID” : 4 , '名称' : '约翰·梅尔' },
{ '身份证' : 5 '名称' : '皮特费城油水' } ,
{ '身份证' : 6 '名称' : '黑星' },
{ 的“id” : 7 }
]
}
模型
在Ext JS 4的模型是非常类似的记录,我们在Ext JS 3。一个关键的区别是,你现在可以在模型上指定代理,以及验证和协会。我们在Ext JS 4中的应用宋模型会是这个样子。
APP /模型/ Song.js的的
Ext.define('Panda.model.Song', {
extend: 'Ext.data.Model',
fields: ['id', 'name', 'artist', 'album', 'played_date', 'station'],
代理: {
类型: “AJAX” ,
网址: “数据/ recentsongs.json的” ,
读者: {
类型: 'JSON'
根 '结果'
}
}
});
正如你可以看到,我们已经在我们的模型中定义的代理。它总体上是好的做法,要做到这一点,因为它允许你加载和保存该模型的实例,而无需存储。另外,当多个门店使用相同的模型,你不重新定义你对他们每个人的代理。
让我们继续前进,并确定我们的站模型。
APP /模型/ Station.js的的
分机定义('Panda.model.Station' , {
延伸: “Ext.data.Model' ,
字段: [ 'ID' , '名' , 'played_date' ],
代理: {
类型: “AJAX” ,
网址: “数据/ stations.json的” ,
读者: {
类型: 'JSON'
根 '结果'
}
}
});
商店
在Ext JS 4,多个商店可以使用相同的数据模型,即使商店将载入他们的数据,从不同的来源。在我们的例子中,车站模型将用于由SearchResults站店,都从不同的位置装载数据。一个返回搜索结果,其他用户的喜爱的电台回报。为了实现这一目标,需要我们的商店之一,覆盖在模型中定义的代理。
APP /店/ SearchResults.js的的
Ext.define('Panda.store.SearchResults', {
extend: 'Ext.data.Store',
requires: 'Panda.model.Station',
model: 'Panda.model.Station',
/ /覆盖模型的默认代理
代理: {
类型: “AJAX” ,
网址: '数据/ searchresults.json' ,
读者: {
类型: 'JSON' ,
根: “结果”
}
}
});
APP /店/ Stations.js的的
Ext.define('Panda.store.Stations', {
extend: 'Ext.data.Store',
requires: 'Panda.model.Station',
model: 'Panda.model.Station'
});
在SearchResults存储的定义,我们有覆盖站模型的定义,提供了不同的代理配置代理。商店的代理商店的负载,而不是模型本身定义的代理方法调用时使用。
请注意,你可以实现你的服务器端检索搜索结果和用户的喜爱的电台,在这种情况下,商店都可以使用默认代理模型中定义的,只有通过不同的参数,请求加载的商店时,有一个API。
最后,让我们创建RecentSongs商店。
APP /店/ RecentSongs.js的的
分机定义(的Panda.store.RecentSongs' , {
延长: “Ext.data.Store ,
模型: “Panda.model.Song”
/ /确保需要你的模型,如果你
/ /不使用的Ext JS 4.0.5
规定: “Panda.model.Song'
});
请注意,在当前版本的Ext JS,商店财产的“模式”不会自动创建一个依赖关系,这就是为什么我们有指定要求,以便能够动态加载模型。
此外,公约,我们总是试图以复数的商店名称,同时保持奇异的模型名称。
将我们的应用程序商店和模型
现在我们已经定义了我们的模型和商店,它的时间将它们添加到我们的应用程序。让我们重新审视我们的application.js文件。
APP / Application.js
Ext.application({
...
models: ['Station', 'Song'],
stores: ['Stations', 'RecentSongs', 'SearchResults']
...
});
使用新的Ext JS 4 MVC的包的另一个好处是,应用程序将自动加载在商店和车型配置的商店和定义模型。然后,它会为每个加载的存储创建一个实例,给它的StoreID等于它的名字。这使我们能够使用商店的名称时,我们把它绑定到一个数据组件,像我们在我们的意见,如商店:“SearchResults”。
应用胶水
现在,我们有我们的看法,模型和商店,它的时间把它们粘合在一起。你的意见逐一视口开始。这将使它更容易调试任何错误的视图配置。让熊猫应用程序通过生成的视口去。
分机定义(“Panda.view.Viewport' , {
延长: “Ext.container.Viewport
视口类通常会希望延长Ext.container.Viewport。这将导致您的应用程序占用所有可用空间,在浏览器窗口。
requires: [
'Panda.view.NewStation',
'Panda.view.SongControls',
'Panda.view.StationsList',
'Panda.view.RecentlyPlayedScroller',
'Panda.view.SongInfo'
],
我们建立了我们的视口的所有视图的依赖关系。这将允许我们使用他们的xtypes,以前配置中我们使用的别名属性的意见。
布局: “适合” ,
initComponent: function() {
this.items = {
xtype: 'panel',
dockedItems: [{
dock: 'top',
xtype: 'toolbar',
height: 80,
items: [{
xtype: 'newstation',
width: 150
}, {
xtype: 'songcontrols',
height: 70,
flex: 1
}, {
xtype: 'component',
html: 'Panda<br>Internet Radio'
}]
}],
layout: {
type: 'hbox',
align: 'stretch'
},
items: [{
width: 250,
xtype: 'panel',
layout: {
type: 'vbox',
align: 'stretch'
},
items: [{
xtype: 'stationslist',
flex: 1
}, {
html: 'Ad',
height: 250,
xtype: 'panel'
}]
}, {
xtype: 'container',
flex: 1,
layout: {
type: 'vbox',
align: 'stretch'
},
items: [{
xtype: 'recentlyplayedscroller',
height: 250
}, {
xtype: 'songinfo',
flex: 1
}]
}]
};
这一点。callParent ();
} } );
自视口扩展的容器,容器不能有对接项目(还),我们已经增加一条,作为我们的视口的单个项目小组。我们此面板定义一个合适的布局,为我们的视口大小相同。
在建筑,这里要注意的最重要的事情之一是,我们还没有定义布局的具体配置,在实际的意见。不喜欢弯曲,宽度,高度的意见确定属性,我们可以很容易地在一个地方的应用程序的整体布局调整,加入到我们的架构的灵活性和可维护性。
应用程序逻辑
在Ext JS 3,我们经常说的意见,自己使用上的按钮,子结合听众的处理程序,重写方法的意见,扩大我们的应用程序的逻辑。然而,就像你不应该在你的HTML标记联CSS样式,最好分开视图定义应用程序的逻辑。在Ext JS 4,我们提供的MVC包controlleres。他们收听到的意见和其他控制器,发射和执行应用程序逻辑来对这些事件采取行动的事件负责。这种设计有几个好处。
一个好处是,你的应用程序逻辑没有被绑定到的意见,这意味着我们可以摧毁和实例化我们的意见,根据需要,而应用程序的逻辑继续处理其他事情,如同步数据的实例。
此外,在Ext JS 3,你可能有许多嵌套的意见,每个应用程序逻辑层加入。通过移动应用程序逻辑控制器,它是集中,使其更容易维护和更改。
最后,控制器基类提供你有很多的功能,使其更容易实现你的应用程序逻辑。
创建我们的控制器
现在,我们有我们的用户界面,建立的模型和商店的基本架构,它的时间来控制我们的应用程序。我们计划有两个控制器,电台和歌曲,让我们为他们创造的定义。
APP /控制器/ Station.js的的
分机定义('Panda.controller.Station“ , {
延长: “Ext.app.Controller'
, init进程 : 函数() {
...
},
...
});
APP /控制器/ Song.js的的
分机定义(“Panda.controller.Song' , {
延长: “Ext.app.Controller' ,
初始化 函数() {
...
},
...
});
包括在您的应用程序的控制器时,该框架将自动加载控制器和调用它的init方法。里面的init方法,你应该设置你的看法和应用程序事件的听众。在较大的应用程序,你可能想在运行时加载额外的控制器。你可以通过使用getController方法。
someAction : 函数() {
VAR 控制器= 这一点。getController (“AnotherController );
/ /记住调用init方法,手动
控制器。的init ();
}
当您在运行时加载额外的控制器,你必须要记得手动加载控制器上调用init方法。
对于我们的示例应用程序的目的,我们将让框架加载并初始化我们加入他们在我们的应用程序定义的控制器阵列控制器。
APP / Application.js
分机。应用({
...
控制器: [ '站' , '松' ]
});
设置监听器
让启动控制器的init函数内部使用的控制方法,控制我们的用户界面的某些部分。
APP /控制器/ Station.js的的
...
init: function() {
this.control({
'stationslist': {
selectionchange: this.onStationSelect
},
'newstation': {
select: this.onNewStationSelect
}
});
}
...
控制方法传递一个对象,其中的键是组件查询。在我们的例子中,组件的查询只使用意见xtypes。但是,使用这些组件的查询,你可以针对非常具体的UI部分。要学习先进的组件查询,你可以参考API文档。
每个查询被绑定到一个侦听器配置。每个监听器的配置里面,我们要听的关键是事件的名称。可用的事件是针对您的查询的组件提供的。在这种情况下,我们使用电网(从我们的StationsList观点延伸)和组合框(从我们的NewStation观点延伸)提供的select事件提供SelectionChange事件。为了找出哪些事件是针对某一特定组件,你可以看看事件中的部分可用于在API文档中的每个组件。
在监听器配置的价值是触发该事件时,被执行的功能。这个函数的范围始终是控制器本身。
我们也成立了一些听众在我们的歌控制器。
APP /控制器/ Song.js的的
...
的init () {
控制({
recentlyplayedscroller“ : {
的SelectionChange 。onSongSelect
}
});
本。应用。({
stationstart : 这一点。onStationStart ,
范围: 本
});
}
...
SelectionChange事件我们RecentlyPlayedScroller视图听此外,我们也设立在这里的应用程序事件侦听器。为此,我们使用的应用程序实例上的方法。每个控制器都有访问的应用程序实例使用this.application引用。
有许多控制器的事件是非常有用的应用程序事件。,只有一个控制器,而不是为每个控制器相同的看法事件监听监听视图的事件,并触发一个应用广泛的事件,别人能听。这也使得控制器彼此沟通,而无需了解或根据对方的存在。
我们的歌控制器正在启动一个新的站有兴趣,因为它需要更新歌曲滚轮和歌曲信息时,发生这种情况。
让我们来看看如何基站控制器,这将是一个负责发射这个stationstart的应用程序事件,实际上这。
APP /控制器/ Station.js的的
...
onStationSelect: function(selModel, selection) {
this.application.fireEvent('stationstart', selection[0]);
}
...
我们只是得到SelectionChange事件提供单一选定的项目,并通过发射stationstart事件时,作为单个参数。
结论
在这篇文章中,我们已经看到在您的应用程序架构的基本技术。当然,有很多的,并在本系列的下一部分,我们将看看一些更先进的控制器技术,并继续通过实施我们的控制器动作,我们的意见,并添加一些更多的细节了我们的熊猫应用程序的接线。