在前文《在Ext JS 5使用ViewControllers》中,简单的介绍了Ext JS 5的一项重要改进——声明式事件监听。在本文,将深度探讨如何使用声明式事件监听啦简化应用程序的视图并减少自定义组件的样板代码。

注意:文章假设你使用的是Ext JS 5.0.1或更高版本。

什么是声明式事件监听?

所谓的“声明式事件监听”,就是指定义在类主体中的监听或在实例的配置对象中使用了listeners配置项。以这种方式来声明事件监听不是Ext JS 5的新功能。在Ext JS 4,可以正在类中声明事件监听,不过只适于处理函数或作用域已定义的情况,例如:

  1. Ext.define('MyApp.view.User', {
  2. extend: 'Ext.panel.Panel',
  3. listeners: {
  4. // 函数必须内联或在之前已被定义:
  5. collapse: function() {
  6. // respond to panel collapse here
  7. }
  8. },
  9. //该方法不能被定义为collapse的处理函数:
  10. onCollapse: function() {
  11. }
  12. });

由于所需的处理函数不能使用类中定义的方法,因而声明式监听在Ext JS 4中的使用有限。开发人员通常会通过重写initComponent方法并使用on方法来添加监听:

  1. Ext.define('MyApp.view.User', {
  2. extend: 'Ext.panel.Panel',
  3. initComponent: function() {
  4. this.callParent();
  5. this.on({
  6. collapse: this.onCollapse,
  7. scope: this
  8. });
  9. },
  10. onCollapse: function() {
  11. console.log(this); // the panel instance
  12. }
  13. });

作用域解析

在Ext JS 5,对listeners配置项做了改进,允许将事件处理指定为字符串来对应方法名。在运行时(触发事件的任何时候),框架会将这些方面解析为实际的函数引用。我们将这一过程称为事件监听作用域解析。

在Ext JS 4,如果明确给出了“作用域”,才能解析字符串处理程序。而在Ext JS 5,在声明“字符串”处理程序而没有明确声明作用域的时候,为默认作用域解析添加了一些特殊规则。

作用域解析有两种结果:组件或视图控制器(ViewController)。无论是哪种结果,都会从组件开始搜索。作用域可能是组件,也可能是视图控制器,如果不是,框架会“爬”到组件的上层直到找到适合的组件或视图控制器。

解析作用域为组件

框架解析作用域的第一种方式是寻找defaultListenerScope配置项为true的组件。对于类中的事件监听声明,搜索会从组件自身开始。

  1. Ext.define('MyApp.view.user.User', {
  2. extend: 'Ext.panel.Panel',
  3. xtype: 'user',
  4. defaultListenerScope: true,
  5. listeners: {
  6. save: 'onUserSave'
  7. },
  8. onUserSave: function() {
  9. console.log('user saved');
  10. }
  11. });

监听被定义在了用户视图的类主体,这意味着框架在提升层次之前会先检查用户视图自身的defaultListenerScope。在当前示例,用户视图将defaultListenerScope设置为了true,那当前监听的作用域将会被解析为用户视图。

对于事件监听被声明在实例配置项的情况,将会条过组件自身,框架会从父容器开始搜索,请参考以下代码:

  1. Ext.define('MyApp.view.main.Main', {
  2. extend: 'Ext.container.Container',
  3. defaultListenerScope: true,
  4. items: [{
  5. xtype: 'user',
  6. listeners: {
  7. remove: 'onUserRemove'
  8. }
  9. }],
  10. onUserRemove: function() {
  11. console.log('user removed');
  12. }
  13. });

对于用户视图的监听是在实例的配置对象中声明的,这意味着框架会跳过用户视图(尽管它定义了defaultListenerScope为true),且会解析为主视图。

解析作用域为视图控制器

在Ext JS 5,引入了新的控制器类型——Ext.app.ViewController。在《在Ext JS 5使用ViewControllers》中详细介绍了视图控制器,因此这里只讨论与视图控制器与事件监听有关的部分。

与Ext.app.Controller可以管理许多视图不同,每一个视图控制器实例只能绑定一个视图实例。视图与视图控制器之间之间一对一的关系允许视图控制器作为视图或视图的条目中事件监听声明的默认作用域。

对于defaultListenerScope,规则同样适用于视图控制器。类层的监听总是会在搜索组件的上层之前先搜索组件自身的视图控制器。

  1. Ext.define('MyApp.view.user.User', {
  2. extend: 'Ext.panel.Panel',
  3. controller: 'user',
  4. xtype: 'user',
  5. listeners: {
  6. save: 'onUserSave'
  7. }
  8. });
  9. Ext.define('MyApp.view.user.UserController', {
  10. extend: 'Ext.app.ViewController',
  11. alias: 'controller.user',
  12. onUserSave: function() {
  13. console.log('user saved');
  14. }
  15. });

上述监听被声明在用户视图的类主体内,由于用户视图有它自己的控制器,框架会解析作用域为UserController。如果用户视图没有自己的控制器,那么作用域会解析到上层。

另一方面,实例层监听会跳过组件并解析为视图控制器上层的父容器,例如:

  1. Ext.define('MyApp.view.main.Main', {
  2. extend: 'Ext.container.Container',
  3. controller: 'main',
  4. items: [{
  5. xtype: 'user',
  6. listeners: {
  7. remove: 'onUserRemove'
  8. }
  9. }]
  10. });
  11. Ext.define('MyApp.view.main.MainController', {
  12. extend: 'Ext.app.ViewController',
  13. alias: 'controller.main',
  14. onUserRemove: function() {
  15. console.log('user removed');
  16. }
  17. });

合并listeners配置项

在Ext JS 4,在基类声明的监听会被子类或实例的listeners配置项的声明完全重写。在Ext JS 5,改进了listeners的API,可适当的合并在基类、子类和实例中的事件监听声明。要想了解其中的行为,可查看以下示例:

  1. Ext.define('BaseClass', {
  2. extend: 'Ext.Component',
  3. listeners: {
  4. foo: function() {
  5. console.log('foo fired');
  6. }
  7. }
  8. });
  9. Ext.define('SubClass', {
  10. extend: 'BaseClass',
  11. listeners: {
  12. bar: function() {
  13. console.log('bar fired');
  14. }
  15. }
  16. });
  17. var instance = new SubClass({
  18. listeners: {
  19. baz: function() {
  20. console.log('baz fired');
  21. }
  22. }
  23. });
  24. instance.fireEvent('foo');
  25. instance.fireEvent('bar');
  26. instance.fireEvent('baz');

在Ext JS 4,上面示例只会输出“baz”,但在Ext JS 5,listeners配置项会被正确的合并并输出“foo bar baz”。这就允许类在需要的时候才去声明监听而不需要知道超类是否已经有了监听。

小结

我们任务声明式的监听可大大简化应用程序中的事件监听定义。结合视图控制器用于处理应用程序的逻辑和视图模型的双向绑定,还可以尽可能的改进应用程序的开发体验。尝试去让我们知道你的想法。

Ext JS 5的声明式事件监听的更多相关文章

  1. cocos2d JS touch屏幕点击事件监听 cc.EventListener.TOUCH

    var self = this; this.touchListener = cc.EventListener.create({ event: cc.EventListener.TOUCH_ONE_BY ...

  2. Ext JS学习第十六天 事件机制event(一) DotNet进阶系列(持续更新) 第一节:.Net版基于WebSocket的聊天室样例 第十五节:深入理解async和await的作用及各种适用场景和用法 第十五节:深入理解async和await的作用及各种适用场景和用法 前端自动化准备和详细配置(NVM、NPM/CNPM、NodeJs、NRM、WebPack、Gulp/Grunt、G

    code&monkey   Ext JS学习第十六天 事件机制event(一) 此文用来记录学习笔记: 休息了好几天,从今天开始继续保持更新,鞭策自己学习 今天我们来说一说什么是事件,对于事件 ...

  3. Node.js 教程 05 - EventEmitter(事件监听/发射器 )

    目录: 前言 Node.js事件驱动介绍 Node.js事件 注册并发射自定义Node.js事件 EventEmitter介绍 EventEmitter常用的API error事件 继承EventEm ...

  4. [JS]笔记12之事件机制--事件冒泡和捕获--事件监听--阻止事件传播

    -->事件冒泡和捕获-->事件监听-->阻止事件传播 一.事件冒泡和捕获 1.概念:当给子元素和父元素定义了相同的事件,比如都定义了onclick事件,点击子元素时,父元素的oncl ...

  5. [No00006A]Js的addEventListener()及attachEvent()区别分析【js中的事件监听】

    1.添加时间监听: Chrom中: addEventListener的使用方式: target.addEventListener(type, listener, useCapture); target ...

  6. js 事件监听 冒泡事件

    js 事件监听  冒泡事件   的取消 [自己写框架时,才有可能用到] <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitiona ...

  7. js 事件监听 兼容浏览器

    js 事件监听 兼容浏览器   ie 用 attachEvent   w3c(firefox/chrome)  用 addEventListener 删除事件监听 ie 用 detachEven   ...

  8. JS通用事件监听函数

    JS通用事件监听函数 版本一 //把它全部封装到一个对象中 var obj={ readyEvent:function (fn){ if(fn==null){ fn=document; } var o ...

  9. js 事件监听封装

    var eventUtil={//添加句柄 //element,节点 //type,事件类型 //handler,函数 addHandler:function(element,type,handler ...

随机推荐

  1. 转:TimeSpan的用法

    转:http://www.cnblogs.com/shuang121/archive/2011/03/03/1969583.html 举例:时间增加一天:DateTime.Parse(txt_Date ...

  2. MySQL 字符集设置

    /*************************************************************************** * MySQL 字符集设置 * 说明: * 数 ...

  3. 《JavaScript Ninja》之闭包

    闭包 闭包是什么,它们是如何工作的 闭包 是一个函数在创建时允许该自身函数访问并操作该自身函数之外的变量时所创建的作用域. 即:闭包可以让函数访问所有的变量和函数,只要这些变量和函数存在于该函数声明时 ...

  4. 13年7月memory point

    IOS/android美术资源压缩相关工具使用,shell编写; 美术资源地图压缩方案: IAP支付objc代码添加, iap cracker/iap free防破解方法, sever端增加php验证 ...

  5. VMDK镜像迁移到KVM

    The vmware system consists of two disks in raw format: the old boot disk and the second one. It is W ...

  6. Codeforces Round #301 (Div. 2) B. School Marks

    其实是很水的一道bfs题,昨晚比赛的时候没看清题意,漏了一个条件. #include<cstdio> #include<cstring> #include<iostrea ...

  7. Mysql数据库搭建-Windows

    首先先下载一下文件包. 下面这个文件包里面包含了已配置的MySQL5.5和连接器. https://www.dropbox.com/s/iu4ifv0m2232ktn/Win_Mysql5_ODBC. ...

  8. 自动刷新ALV

    转自http://blog.sina.com.cn/s/blog_701594f40100l8ms.html ABAP:利用SAP定时器自动刷新ALV 曾于无意之中发现,SAP系统中有个名为CL_GU ...

  9. C语言的位运算

    位运算加速技巧1. 如果乘上一个2的倍数数值,可以改用左移运算(Left Shift) 加速 300% x = x * 2;x = x * 64;//改为:x = x << 1; // 2 ...

  10. 如何优雅的写C++代码(一)

    // get the greatest power of two that is a divisor of n: return n&-n; // swap two integers a and ...