原文:Declarative Listeners in Ext JS 5
在前文《在Ext JS 5使用ViewControllers》中,简单的介绍了Ext JS 5的一项重要改进——声明式事件监听。在本文,将深度探讨如何使用声明式事件监听啦简化应用程序的视图并减少自定义组件的样板代码。
注意:文章假设你使用的是Ext JS 5.0.1或更高版本。
所谓的“声明式事件监听”,就是指定义在类主体中的监听或在实例的配置对象中使用了listeners配置项。以这种方式来声明事件监听不是Ext JS 5的新功能。在Ext JS 4,可以正在类中声明事件监听,不过只适于处理函数或作用域已定义的情况,例如:
Ext.define(‘MyApp.view.User‘, { extend: ‘Ext.panel.Panel‘, listeners: { // 函数必须内联或在之前已被定义: collapse: function() { // respond to panel collapse here } }, //该方法不能被定义为collapse的处理函数: onCollapse: function() { } });
Ext.define(‘MyApp.view.User‘, { extend: ‘Ext.panel.Panel‘, initComponent: function() { this.callParent(); this.on({ collapse: this.onCollapse, scope: this }); }, onCollapse: function() { console.log(this); // the panel instance } });
在Ext JS 5,对listeners配置项做了改进,允许将事件处理指定为字符串来对应方法名。在运行时(触发事件的任何时候),框架会将这些方面解析为实际的函数引用。我们将这一过程称为事件监听作用域解析。
在Ext JS 4,如果明确给出了“作用域”,才能解析字符串处理程序。而在Ext JS 5,在声明“字符串”处理程序而没有明确声明作用域的时候,为默认作用域解析添加了一些特殊规则。
作用域解析有两种结果:组件或视图控制器(ViewController)。无论是哪种结果,都会从组件开始搜索。作用域可能是组件,也可能是视图控制器,如果不是,框架会“爬”到组件的上层直到找到适合的组件或视图控制器。
框架解析作用域的第一种方式是寻找defaultListenerScope配置项为true的组件。对于类中的事件监听声明,搜索会从组件自身开始。
Ext.define(‘MyApp.view.user.User‘, { extend: ‘Ext.panel.Panel‘, xtype: ‘user‘, defaultListenerScope: true, listeners: { save: ‘onUserSave‘ }, onUserSave: function() { console.log(‘user saved‘); } });
Ext.define(‘MyApp.view.main.Main‘, { extend: ‘Ext.container.Container‘, defaultListenerScope: true, items: [{ xtype: ‘user‘, listeners: { remove: ‘onUserRemove‘ } }], onUserRemove: function() { console.log(‘user removed‘); } });
在Ext JS 5,引入了新的控制器类型——Ext.app.ViewController。在《在Ext JS 5使用ViewControllers》中详细介绍了视图控制器,因此这里只讨论与视图控制器与事件监听有关的部分。
与Ext.app.Controller可以管理许多视图不同,每一个视图控制器实例只能绑定一个视图实例。视图与视图控制器之间之间一对一的关系允许视图控制器作为视图或视图的条目中事件监听声明的默认作用域。
对于defaultListenerScope,规则同样适用于视图控制器。类层的监听总是会在搜索组件的上层之前先搜索组件自身的视图控制器。
Ext.define(‘MyApp.view.user.User‘, { extend: ‘Ext.panel.Panel‘, controller: ‘user‘, xtype: ‘user‘, listeners: { save: ‘onUserSave‘ } }); Ext.define(‘MyApp.view.user.UserController‘, { extend: ‘Ext.app.ViewController‘, alias: ‘controller.user‘, onUserSave: function() { console.log(‘user saved‘); } });
Ext.define(‘MyApp.view.main.Main‘, { extend: ‘Ext.container.Container‘, controller: ‘main‘, items: [{ xtype: ‘user‘, listeners: { remove: ‘onUserRemove‘ } }] }); Ext.define(‘MyApp.view.main.MainController‘, { extend: ‘Ext.app.ViewController‘, alias: ‘controller.main‘, onUserRemove: function() { console.log(‘user removed‘); } });
在Ext JS 4,在基类声明的监听会被子类或实例的listeners配置项的声明完全重写。在Ext JS 5,改进了listeners的API,可适当的合并在基类、子类和实例中的事件监听声明。要想了解其中的行为,可查看以下示例:
Ext.define(‘BaseClass‘, { extend: ‘Ext.Component‘, listeners: { foo: function() { console.log(‘foo fired‘); } } }); Ext.define(‘SubClass‘, { extend: ‘BaseClass‘, listeners: { bar: function() { console.log(‘bar fired‘); } } }); var instance = new SubClass({ listeners: { baz: function() { console.log(‘baz fired‘); } } }); instance.fireEvent(‘foo‘); instance.fireEvent(‘bar‘); instance.fireEvent(‘baz‘);
我们任务声明式的监听可大大简化应用程序中的事件监听定义。结合视图控制器用于处理应用程序的逻辑和视图模型的双向绑定,还可以尽可能的改进应用程序的开发体验。尝试去让我们知道你的想法。
作者:Phil Guerrant
Phil is a Sencha software engineer who works on Ext JS. He has over 10 years of experience as a developer and specializes in HTML5 and web development, UI, and agile methodologies.
原文地址:http://blog.csdn.net/tianxiaode/article/details/39206763