在前文《在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. LinearLayout 控件

    LinearLayout 控件,垂直显示各控件一行一个显示,比较好控件. 用RelativeLayout多个控件会堆在一起 <LinearLayout xmlns:android="h ...

  2. jquery-ui 进度条

    <!DOCTYPE html> <html> <head> <meta charset="utf8" /> <title> ...

  3. TC HTB r2q

    HTB: quantum of class 10001 is big. Consider r2q change. 根据HTB的官方文档显示,quantum是在可以“借”的情况下,一次可以“借”多少,并 ...

  4. Android内存管理机制之一:low memory killer

    转载自http://www.miui.com/thread-29268-1-1.html 准备写这个专题之前,心里是有点忐忑的.首先Android内存管理机制相当复杂,想要讲清楚比较困难:其次对于绝大 ...

  5. EasyUI修改DateBox和DateTimeBox的默认日期格式

      最近整理Easyui控件的时候,对Easyui的DateBox控件和DateTimeBox控件进行了梳理,而我之所以将EasyUI的DateBox控件和DateTimeBox控件放在一起,归为一类 ...

  6. poj 1260 dp

    Description In Pearlania everybody is fond of pearls. One company, called The Royal Pearl, produces ...

  7. 启动tomcat不出现命令窗口

    有个软件要安装在U盘中,B/S结构,用tomcat做应用服务器,客户要求tomcat不能注册为系统服务,启动时tomcat启动时不能出现命令行窗口,怎么实现? 根据你的问题描述,猜测你的部署系统是Wi ...

  8. tyvj1013 - 找啊找啊找GF ——二维背包变种

    题目链接:https://www.tyvj.cn/Problem_Show.aspx?id=1013 好吧,这题没节操=_= 状态f[u,v,i]表示:消费u的人民币和v的人品同时泡到i个mm所需要的 ...

  9. C++@sublime GDB调试

    正文转自:http://www.cppblog.com/lucency/archive/2012/08/09/59214.html 之前在网上搜索了好久使用sublime调试C和C++的文章,但是徒劳 ...

  10. spring源码学习之:xml配置文件标签自定义

    Spring框架从2.0版本开始,提供了基于Schema风格的XML扩展机制,允许开发者扩展最基本的spring配置文件(一 般是classpath下的spring.xml).试想一下,如果我们直接在 ...