【翻译】在Ext JS 5种使用ViewControllers

时间:2022-06-26 22:53:08

原文:Using ViewControllers in Ext JS 5

简单介绍

在Ext JS 5中,在应用程序架构方面提供了一些令人兴奋的改进,如加入了ViewModels、MVVM以及viewControllers来加强MVC应用程序。

最重要的是。这些选择并不相互排斥,因此,能够採用增量的方式来介绍这些功能,又或者将他们混合在一起。

回想控制器

在Ext JS 4,控制器就是一个从Ext.app.Controller的派生的类。

这些控制器会使用相似CSS选择器(称为组件查询)来查找组件并对他们的事件做出响应。

还能够使用refs来选择或返回组件实例。

这些控制器会在应用程序启动时被创建,且会存在于整个应用程序的生命周期。

在控制器的生命周期内,控制器所关注视图能够说是来了又去。甚至可能是一个控制器管理着非常多实例。

挑战

对于大型应用程序,这技术可能会遇到某些挑战。

在这样的环境中,视图和控制器可能是由多个开发团队开发并继承到终于的应用程序的。

为来确保控制器仅仅对他们关注的视图做出响应将会是一项艰难的工作。此外,对于开发者来说,通常都会希望在应用程序启动时限制控制器创建的数量。

尽管能够通过努力延迟控制器的创建,可是他们不能被销毁,因此在他们不再须要的时候仍然会保持在内存中。

ViewControllers

尽管Ext JS 5能向后兼容这些控制器。但它引入了一种新型的控制器,可设计来处理这些挑战: Ext.app.ViewController。

ViewController通过下面方式来实现操作:

  • 简化视图的listeners和reference配置项的使用
  • 利用视图的生命周期来自己主动管理他们相关的ViewController
  • 基于一对一来关联管理视图以降低ViewController的复杂度
  • 提供封装以使嵌套视图更可靠
  • 为相关视图之上的不论什么层保留选择组件和监听他们事件的能力

Listeners

配置项listeners尽管不是新的。可是在Ext JS 5为它加入了新的能力。新的listeners功能会在未来的文章《Declarative Listeners in Ext JS 5》中进行全面的探讨。

针对ViewControllers,我们来看两个演示样例。第一个是最主要的,在视图的子组件中使用listeners配置项:

Ext.define('MyApp.view.foo.Foo', {
extend: 'Ext.panel.Panel',
xtype: 'foo',
controller: 'foo', items: [{
xtype: 'textfield',
fieldLabel: 'Bar',
listeners: {
change: 'onBarChange' // no scope given here
}
}]
}); Ext.define('MyApp.view.foo.FooController', {
extend: 'Ext.app.ViewController',
alias: 'controller.foo', onBarChange: function (barTextField) {
// called by 'change' event
}
});

在上面代码的listeners中,使用了一个命名事件句柄(onBarChange),但没有指定作用域(scope)。在事件系统内部。会将Bar文本字段的作用域解析为其所属的ViewController。

在过去,listeners配置项会预留给组件的创建者使用。那么,怎样让视图去监听自己的事件呢,并且又能够让它的基类来触发呢?解决之道就是使用显式的作用域:

Ext.define('MyApp.view.foo.Foo', {
extend: 'Ext.panel.Panel',
xtype: 'foo',
controller: 'foo', listeners: {
collapse: 'onCollapse',
scope: 'controller'
}, items: [{
...
}]
});

以上演示样例代码利用了两个Ext JS 5的新功能:命名的作用域和声明性监听。

在这里的重点是命名的作用域。

在这里可使用两个有效的作用域命名:this和controller。

在写MVC应用程序的时候,基本上总是会使用controller,这不用说指的就是视图的ViewController(不是创建视图实例的那个视图的ViewController )。

由于视图是Ext.Component的一种类型,因而可为它定义一个xtype。以便其它视图以相同的方式来创建创建视图实例及其文本字段。为了探讨怎样将这些整合在一起。考虑一下怎样使用改视图,比如:

Ext.define('MyApp.view.bar.Bar', {
extend: 'Ext.panel.Panel',
xtype: 'bar',
controller: 'bar', items: [{
xtype: 'foo',
listeners: {
collapse: 'onCollapse'
}
}]
});

在这样的情况下,Bar视图创建了Foo视图的一个实例作为它的一个子组件。

此外,还为Foo视图绑定了collapse事件。

在之前版本号的Ext JS或Sencha Touch,这些声明将会产生冲突。而在Ext JS 5,正如预期的那样得到了解决。

通过Foo视图声明的监听仅仅会在Foo的ViewController内触发,而在Bar视图声明的监听仅仅会在Bar的ViewController内触发。

Reference(引用)

在编写控制器逻辑的时候,最烦的就是须要获取所需的组件来完毕仅仅能的操作,比如:

Ext.define('MyApp.view.foo.Foo', {
extend: 'Ext.panel.Panel',
xtype: 'foo',
controller: 'foo', tbar: [{
xtype: 'button',
text: 'Add',
handler: 'onAdd'
}], items: [{
xtype: 'grid',
...
}]
}); Ext.define('MyApp.view.foo.FooController', {
extend: 'Ext.app.ViewController',
alias: 'controller.foo', onAdd: function () {
// ... get the grid and add a record ...
}
});

如今应该怎样起获取网格组件?在Ext JS 4,能够使用refs配置项或者一些其它方式来寻找组件。所以这些技术都要求在网格上放置一些可用来识别且能唯一标识网格的属性。老技术会使用id配置项(Ext.getCmp)或者itemId(适用于refs或一些组件查询语法)配置项。

使用id的优势是可实现高速查找,但必须确保这标识在整个应用程序或DOM中是唯一的,该方法并不可取。

使用itemId或其它一些查询会更灵活,但这须要运行搜索来寻找所需的组件。

在Ext JS 5能够使用新的reference配置项来实现,仅仅须要加入reference到网格并使用lookupReference就能够来获取它:

Ext.define('MyApp.view.foo.Foo', {
extend: 'Ext.panel.Panel',
xtype: 'foo',
controller: 'foo', tbar: [{
xtype: 'button',
text: 'Add',
handler: 'onAdd'
}], items: [{
xtype: 'grid',
reference: 'fooGrid'
...
}]
}); Ext.define('MyApp.view.foo.FooController', {
extend: 'Ext.app.ViewController',
alias: 'controller.foo', onAdd: function () {
var grid = this.lookupReference('fooGrid');
}
});

这相似于分配了一个名为fooGrid的itemId并运行“this.down('#fooGrid')”。只是,这在底层的实现是不同的,并且差别非常大。首先。reference配置项会将组件自身注冊到它所属的视图(一般是ViewController中标识)。

其次,lookupReference方法仅仅去查询缓存以确定是否须要刷新引用(指的是容器的add或remove操作)。

假设一切顺利,就可从缓存中返回引用。

另外,伪代码例如以下:

lookupReference: (reference) {
var cache = this.references;
if (!cache) {
Ext.fixReferences(); // fix all references
cache = this.references; // now the cache is valid
}
return cache[reference];
}

也就是说,这样就不须要搜索且不会由于是一次成型的,会因容器的加入或删除子组件而出现故障。正如所示。这样的优点就是提供了效率。

封装(Encapsulation)

尽管在Ext JS 4种使用选择器的实现非常灵活,但同一时候也存在一定的风险。

其实,这些选择器能够“看到”全部的组件层次结构,既强大也easy出现错误。比如,一个控制器在隔离运行时能够运转正常。但一旦引入了其它视图。就能够会失败,原因是它的选择器可能会意外的匹配了新的视图。

这些问题可通过下面做法来进行管理。只是,当在ViewController中使用listeners或references时,要解决这些问题就变得不可能了。这是由于listeners和references配置项仅仅能连接他们所属的ViewController。在视图内部,能够使用随意唯一的reference值。由于视图知道这些名字不会曝露给视图的创建者。

相同,listeners也能够保留给它所属的ViewController而不会意外的分发到其它使用错误的选择器的控制器的事件处理中。尽管监听会优先于选择器,但在须要以选择器为基础的时候,这两种机制能够一起工作。

要实现这个,视图须要通过它所属视图的ViewController来触发事件。在ViewController有一个辅助方法能够用了实现这个:fireViewEvent,比如:

Ext.define('MyApp.view.foo.FooController', {
extend: 'Ext.app.ViewController',
alias: 'controller.foo', onAdd: function () {
var record = new MyApp.model.Thing();
var grid = this.lookupReference('fooGrid');
grid.store.add(record); this.fireViewEvent('addrecord', this, record);
}
});

在视图的创建者可使用标准形式的监听:

Ext.define('MyApp.view.bar.Bar', {
extend: 'Ext.panel.Panel',
xtype: 'bar',
controller: 'bar', items: [{
xtype: 'foo',
listeners: {
collapse: 'onCollapse',
addrecord: 'onAddRecord'
}
}]
});

监听和事件域

在Ext JS 4.2,MVC事件分发会被一般化为对事件域的引用。

事件域会在事件触发时截获事件并将他们分发到由选择器匹配所控制的控制器中。

尽管其它域仅仅有有限的选择器。但组件事件域具有完整的组件查询选择器。

在Ext JS 5,每个ViewController会创建一个名为view的新的事件域的实例。该事件域同意ViewController去使用标准的隐式的限制了它的作用域为所属视图的listen或control方法。它还加入了一个特定的选择了来匹配视图自身。

Ext.define('MyApp.view.foo.FooController', {
extend: 'Ext.app.ViewController',
alias: 'controller.foo', control: {
'#': { // matches the view itself
collapse: 'onCollapse'
},
button: {
click: 'onAnyButtonClick'
}
}
});

从以上代码能够看出listeners和选择器之间的差别。

选择器button可匹配视图及子视图(不论深度,即使是是重孙视图)中的不论什么按钮,也就是说,基于选择器的处理不会理会封装边界,改行为与曾经的Ext.app.Controller的行为是一致的,在有限的情况下这是非常有用的技术。

最后。事件域会遵循嵌套并有效的将事件按照视图层次往上冒泡。也就是说,当一个事件触发时,它首先会传递到不论什么标准的listeners中。然后,它会传递到它所属的ViewController,接着通过它的父ViewController(假设存在)传递到最顶层。终于,事件会被传递到标准的组件事件域,以便由Ext.app.Controller派生的控制器处理。

生命周期

大型应用程序经常使用的技术是会依据须要动态创建所需的控制器。这有助于降低应用程序的载入时间,且有助于在运行时通过不激活潜在的控制器已提供性能。

这在之前的版本号是不可能的,控制器一旦创建,就会在应用程序中保持活动状态,不会被销毁并释放资源。相同。这也没改变一个控制器可能包括随意数目的相关视图(包括没有视图)这一事实。

然而。ViewController会在组件生命周期的早期创建并将它的整个生命周期绑定在了视图。当视图被销毁的时候。ViewController相同也会销毁。这意味着。ViewController从此不用在没有视图或非常多视图的时候被强迫去管理状态。

这样的一对一的管理意味着引用跟踪被简化了,并且不再会轻易的因组件的销毁而出现泄漏。ViewController可在它生命周期内不论什么关键点内实现不论什么方法来处理事务。

beforeinit——该方法可被重写,它会在视图调用initComponent方法之前运行。该方法会在控制器创建之后马上被调用,而这会在组件的构造函数之内在调用initConfig方法期间发生。

init——在视图调用initComponent方法不久后会调用该方法。

这一般会是视图初始化后,运行控制器初始化的时候,

initViewModel——在创建视图的ViewModel(假设存在)时会调用该方法。

destroy——清理不论什么资源(确保调用了callParent方法)。

小结

我们相信ViewController将会大大简化你的MVC应用程序。他们还能够与ViewModels一起使用。因此。你能够结合这些方法以及他们的各自优势。我们非常兴奋即将公布正式版以及看到这些在你的应用程序中所做的改进。

作者:Don Griffin
Don Griffin is a member of the Ext JS core team. He was an Ext JS user for 2 years before joining Sencha and has over 20 years of software engineering experience on a broad range of platforms. His experience includes designing web application front-ends and back-ends, native GUI applications, network protocols and device drivers. Don’s passion is to build world class products that people love to use.

【翻译】在Ext JS 5种使用ViewControllers的更多相关文章

  1. 【翻译】Ext JS最新技巧——2016-3-4

    原文:Top Support Tips Kevin Cassidy:Grid水印 Ext JS的Grid是一个便于在布局中显示信息的伟大工具.有些用户可能会希望将这些信息打印为会议资料或宣传材料,而且 ...

  2. 【翻译】Ext JS最新技巧——2015-8-11

    原文:Top Support Tips Seth Lemmons:使用棒极了的Awesome Font Ext JS 6附带了一个新的海卫一主题,可以使用Font Awesome字体作为背景图像的图标 ...

  3. 【翻译】Ext JS 6有什么新东西?

    工具包ToolKits 发布 包的命名 Fashion 图表 ItemEdit插件 网格 电子表格 可操作模式Actionable Mode和可访问性 LazyItems插件 屏幕阅读器支持可访问性 ...

  4. 【翻译】Ext JS最新技巧——2014-8-13

    原文:Top Support Tips Greg Barry:新的框架. 新的文档类型(Doctype) 在Ext JS 5,只支持IE8+,因此不再古力用户使用严格的HTML文档类型.现在,推荐使用 ...

  5. 【翻译】Ext JS——高效的编码风格指南

    原文:ExtJS - Efficient coding style guide 作者:Raja 切勿使用"new"关键字:在Ext JS中,使用"new"关键字 ...

  6. 【翻译】Ext JS 5的委托事件和手势

    原文:Delegated Events and Gestures in Ext JS 5 简介 Ext JS在5之前的版本,被设计为专用于传统鼠标输入的桌面设备使用.而从5开始,添加了对触屏输入的支持 ...

  7. 【翻译】Ext JS最新技巧

    原文:Top Support Tips Mitchell Simoens:控制滚动指示器的自动隐藏 Sencha Touch有一个跨平台的,在所有平台看起来和工作效果都一样的滚动条.两条轴(x和y,水 ...

  8. 【翻译】Ext JS最新技巧——2014-10-30

    原文:Top Support Tips Greg Barry:Ext JS 5的ExtraParams Ext JS 4同意用户直接将extraParams加入到一个链接,相似例如以下代码: Ext. ...

  9. 【翻译】Ext JS 6.2 早期访问版本发布

    原文:Announcing Ext JS 6.2 Early Access 非常开心,Sencha Ext JS 6.2早期访问版本今天发布了.早期访问版本的主要目的是为了让大家进行测试并评估Ext ...

随机推荐

  1. Vagrant使用简介

    一.简介: Vagrant是一款用于构建及配置虚拟开发环境的软件,基于Ruby,主要以命令行的方式运行.主要使用Oracle的开源VirtualBox虚拟化系统,与Chef,Salt,Puppet等环 ...

  2. 如何更好的通过Inflate layout的方式来实现自定义view

    本篇文章讲的是如何用现有控件产生一个组合控件的方法,十分简单实用.现在开始! 一.需求 我们要实现一个有红点和文字的按钮控件,就像下面这样: 二.实现 我的思路是让一个button和一个textvie ...

  3. NuGet学习笔记3——搭建属于自己的NuGet服务器

    文章导读 创建NuGetServer Web站点 发布站点到IIS 添加本地站点到包包数据源 在上一篇NuGet学习笔记(2) 使用图形化界面打包自己的类库 中讲解了如何打包自己的类库,接下来进行最重 ...

  4. jsp上传excel文件并导入数据库

    1,excel文件的上传 需要借助jar包:commons-fileupload-1.2.1.jar以及commons-io-1.3.2.jar 前端的html文件 <form id=&quot ...

  5. Docker 使用指南 &lpar;二&rpar;—— 搭建本地仓库

    版权声明:本文由田飞雨原创文章,转载请注明出处: 文章原文链接:https://www.qcloud.com/community/article/94 来源:腾云阁 https://www.qclou ...

  6. nginx-url重写

    location /game_web{ if (!-e $request_filename){//请求不是文件或者目录 rewrite ^/game_web/(\/init/$ last; break ...

  7. 关于蓝桥杯嵌入式STM32的一点收获

    各社团成员培训时自己总结的一点材料,直接粘过来的,可能有些朋友看不明白,总之这个比赛吧:有很多技巧,掌握到技巧能省我们半个月时间,我说的是针对这个比赛,对于STM32还是要多多练习,总之STM32还是 ...

  8. html标记语言 --框架

    html标记语言 --框架 六.框架 1.什么是框架 框架将浏览器划分成不同的部分,每一部分加载不同的网页 实现同一浏览器窗口中加载多个页面的效果. 语法格式<frameset>..... ...

  9. Mint-UI Picker 三级联动

    Mint-UI Picker组件的三级联动 HTML: <mt-picker :slots="slots" value-key="name" @chang ...

  10. getElementById和&dollar;&lpar;&rpar;获取值一点注意事项

    <script type="text/javascript"> window.onload = function () { var obj = document.get ...