标签:extjs 5 mvc viewcontroller
原文:Using ViewControllers in Ext JS 5
在Ext JS 5中,在应用程序架构方面提供了一些令人兴奋的改进,如添加了ViewModels、MVVM以及viewControllers来加强MVC应用程序。最重要的是,这些选择并不互斥,因此,可以采用增量的方式来介绍这些功能,又或者将他们混合在一起。
在Ext JS 4,控制器就是一个从Ext.app.Controller的派生的类。这些控制器会使用类似CSS选择器(称为组件查询)来查找组件并对他们的事件做出响应。还可以使用refs来选择或返回组件实例。
这些控制器会在应用程序启动时被创建,且会存在于整个应用程序的生命周期。在控制器的生命周期内,控制器所关注视图可以说是来了又去。甚至可能是一个控制器管理着很多实例。
对于大型应用程序,这技术可能会遇到某些挑战。
在这种环境中,视图和控制器可能是由多个开发团队开发并继承到最终的应用程序的。为来确保控制器只对他们关注的视图做出响应将会是一项艰难的工作。此外,对于开发人员来说,通常都会希望在应用程序启动时限制控制器创建的数量。虽然可以通过努力延迟控制器的创建,但是他们不能被销毁,因此在他们不再需要的时候仍然会保持在内存中。
虽然Ext JS 5能向后兼容这些控制器,但它引入了一种新型的控制器,可设计来处理这些挑战: Ext.app.ViewController。ViewController通过以下方式来实现操作:
配置项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 } });
Ext.define(‘MyApp.view.foo.Foo‘, { extend: ‘Ext.panel.Panel‘, xtype: ‘foo‘, controller: ‘foo‘, listeners: { collapse: ‘onCollapse‘, scope: ‘controller‘ }, items: [{ ... }] });
Ext.define(‘MyApp.view.bar.Bar‘, { extend: ‘Ext.panel.Panel‘, xtype: ‘bar‘, controller: ‘bar‘, items: [{ xtype: ‘foo‘, listeners: { collapse: ‘onCollapse‘ } }] });
在编写控制器逻辑的时候,最烦的就是需要获取所需的组件来完成只能的操作,例如:
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.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]; }
也就是说,这样就不需要搜索且不会由于是一次成型的,会因容器的添加或删除子组件而出现问题。正如所看到的,这样的好处就是提供了效率。
虽然在Ext JS 4种使用选择器的实现非常灵活,但同时也存在一定的风险。事实上,这些选择器可以“看到”所有的组件层次结构,既强大也容易出现错误。例如,一个控制器在隔离运行时可以运转正常,但一旦引入了其他视图,就可以会失败,原因是它的选择器可能会意外的匹配了新的视图。
这些问题可通过以下做法来进行管理,不过,当在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‘ } } });
大型应用程序常用的技术是会根据需要动态创建所需的控制器。这有助于减少应用程序的加载时间,且有助于在运行时通过不激活潜在的控制器已提供性能。这在之前的版本是不可能的,控制器一旦创建,就会在应用程序中保持活动状态,不会被销毁并释放资源。同样,这也没改变一个控制器可能包含任意数目的相关视图(包括没有视图)这一事实。
然而,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,布布扣,bubuko.com
【翻译】在Ext JS 5种使用ViewControllers
标签:extjs 5 mvc viewcontroller
原文地址:http://blog.csdn.net/tianxiaode/article/details/26631673