在前文《在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. JQuery事件手册

    blur.focus     blur失去焦点:focus获得焦点 load 当指定的元素(及子元素)已加载时,会发生 load() 事件 resize 当调整浏览器窗口的大小时,发生 resize ...

  2. ios开发环境 分支语句 、 循环结构(for) 、 循环结构

    1 完成命令解析程序 1.1 问题 有命令解析程序,该程序提供三个功能选项供用户选择,用户选择某功能后,程序在界面上输出用户所选择的功能名称.程序的交互效果如图-1所示: 图-1 由上图可以看出,程序 ...

  3. curl 发送带有Authorization的post请求命令

    curl --user user:password  -d "param1=111&param2=222" "http://127.0.0.1/cmd"

  4. Ensemble Approaches分类技术

    所谓ensemble learning,简单来说,是指综合多种基础模型或弱分类器来完成最终的决策的机器学习方法. Bagging和Boosting(之前所提到的Adaboost)都属于这类方法. Co ...

  5. Link Aggregation and LACP with Open vSwitch

    In this post, I’m going to show you how to use link aggregation (via the Link Aggregation Control Pr ...

  6. hdu 4253 Two Famous Companies BZOJ 2654 tree

    [题意]:给出n个点,m条边,边分为两种,一种是A公司的,一种是B公司的.边上有权值,问用n-1条边把n个点连起来的最小费用是多少,其中A公司的边刚好有k条.题目保证有解. 思路:我们发现,如果我们给 ...

  7. UI学习笔记---第六天

    UIControl及其子类 UISegmentedControl的用法 UISegmentedControl是iOS中得分段控件,每个segment都能被点击,相当于集成了若干个button.通常我们 ...

  8. android中ImageView讲解

    1.看布局文 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns ...

  9. 如何在远程计算机上运行PowerShell

    问题: 不能在WORKGROUP里面的远程计算机里运行PowerShell指令,报错为用户名密码错 解决方法: 把两台机器上(远程计算机其和本机)都加入到trustedhosts 具体请参考 http ...

  10. Java——各种日期的获取(来自别人分享)

     import java.text.DateFormat; import java.text.ParsePosition; import java.text.SimpleDateFormat; i ...