解释 ExtJS 4 事件处理触发应用程序范围的事件

2022-08-30 04:32:01

我最近开始学习ExtJS,并且很难理解如何处理事件。我没有以前任何版本的ExtJS的经验。

通过阅读各种手册,指南和文档页面,我已经弄清楚了如何使用它,但我不清楚它是如何工作的。我已经找到了几个旧版本的ExtJS教程,但我不确定它们在ExtJS 4中的适用程度。

我特别关注诸如此类的“最终决定词”

  • 事件处理函数传递哪些参数?有没有一组标准的参数总是被传递?
  • 如何为我们编写的自定义组件定义自定义事件?我们如何触发这些自定义事件?
  • 返回值(真/假)是否会影响事件气泡的方式?如果不是,我们如何从事件处理程序内部或外部控制事件冒泡?
  • 是否有注册事件侦听器的标准方法?(到目前为止,我遇到了两种不同的方法,我不确定为什么使用每种方法)。

例如,这个问题使我相信事件处理程序可以接收相当多的参数。我看过其他教程,其中处理程序只有两个参数。有哪些变化?


答案 1

让我们从描述 DOM 元素的事件处理开始。

DOM 节点事件处理

首先,您不希望直接使用DOM节点。相反,您可能希望使用Ext.Element接口。为了分配事件处理程序,创建了 Element.addListenerElement.on(它们是等效的)。因此,例如,如果我们有html:

<div id="test_node"></div>

我们想要添加事件处理程序。
让我们检索:clickElement

var el = Ext.get('test_node');

现在,让我们检查文档中的点击事件。它的处理程序可能有三个参数:

click( Ext.EventObject e, HTMLElement t, Object eOpts )

知道了所有这些东西,我们可以分配处理程序:

//       event name      event handler
el.on(    'click'        , function(e, t, eOpts){
  // handling event here
});

小部件事件处理

Widgets事件处理与DOM节点事件处理非常相似。

首先,小部件事件处理是通过利用Ext.util.Observable mixin来实现的。为了正确处理事件,您的小部件必须包含作为 mixin。默认情况下,所有内置小部件(如面板,窗体,树,网格等)都作为mixin。Ext.util.ObservableExt.util.Observable

对于小部件,有两种分配处理程序的方法。第一个 - 是在方法(或)上使用。例如,让我们创建小部件并为其分配事件。首先,您应该检查事件的文档以获取处理程序的参数:addListenerButtonclick

单击( Ext.button.Button.Button this, Event e, Object eOpts )

现在让我们使用:on

var myButton = Ext.create('Ext.button.Button', {
  text: 'Test button'
});
myButton.on('click', function(btn, e, eOpts) {
  // event handling here
  console.log(btn, e, eOpts);
});

第二种方法是使用小部件的侦听器配置:

var myButton = Ext.create('Ext.button.Button', {
  text: 'Test button',
  listeners : {
    click: function(btn, e, eOpts) {
      // event handling here
      console.log(btn, e, eOpts);
    }
  }
});

请注意,小部件是一种特殊类型的小部件。可以使用处理程序配置将单击事件分配给此小部件:Button

var myButton = Ext.create('Ext.button.Button', {
  text: 'Test button',
  handler : function(btn, e, eOpts) {
    // event handling here
    console.log(btn, e, eOpts);
  }
});

自定义事件触发

首先,您需要使用addEvents方法注册事件:

myButton.addEvents('myspecialevent1', 'myspecialevent2', 'myspecialevent3', /* ... */);

使用该方法是可选的。正如对此方法的评论所说,没有必要使用此方法,但它为事件文档提供了位置。addEvents

要触发事件,请使用 fireEvent 方法:

myButton.fireEvent('myspecialevent1', arg1, arg2, arg3, /* ... */);

arg1, arg2, arg3, /* ... */将传递到处理程序中。现在我们可以处理您的事件:

myButton.on('myspecialevent1', function(arg1, arg2, arg3, /* ... */) {
  // event handling here
  console.log(arg1, arg2, arg3, /* ... */);
});

值得一提的是,在定义新 widget 时,插入 addEvents 方法调用的最佳位置是 widget 的方法:initComponent

Ext.define('MyCustomButton', {
  extend: 'Ext.button.Button',
  // ... other configs,
  initComponent: function(){
    this.addEvents('myspecialevent1', 'myspecialevent2', 'myspecialevent3', /* ... */);
    // ...
    this.callParent(arguments);
  }
});
var myButton = Ext.create('MyCustomButton', { /* configs */ });

防止事件冒泡

为了防止冒泡,你可以使用 Ext.EventObject.preventDefault()。为了防止浏览器的默认操作,请使用 Ext.EventObject.stopPropagation()return false

例如,让我们将单击事件处理程序分配给按钮。如果没有单击左键,则阻止默认浏览器操作:

myButton.on('click', function(btn, e){
  if (e.button !== 0)
    e.preventDefault();
});

答案 2

触发应用程序范围的事件

如何使控制器相互通信...

除了上面非常好的答案之外,我还想提到应用程序范围的事件,这些事件在MVC设置中非常有用,以实现控制器之间的通信。(extjs4.1)

假设我们有一个控制器站(Sencha MVC示例),带有一个选择框:

Ext.define('Pandora.controller.Station', {
    extend: 'Ext.app.Controller',
    ...

    init: function() {
        this.control({
            'stationslist': {
                selectionchange: this.onStationSelect
            },
            ...
        });
    },

    ...

    onStationSelect: function(selModel, selection) {
        this.application.fireEvent('stationstart', selection[0]);
    },    
   ...
});

当选择框触发更改事件时,将触发该函数。onStationSelect

在该函数中,我们看到:

this.application.fireEvent('stationstart', selection[0]);

这将创建并触发一个应用程序范围的事件,我们可以从任何其他控制器侦听该事件。

因此,在另一个控制器中,我们现在可以知道何时更改了工作站选择框。这是通过收听来完成的,如下所示:this.application.on

Ext.define('Pandora.controller.Song', {
    extend: 'Ext.app.Controller', 
    ...
    init: function() {
        this.control({
            'recentlyplayedscroller': {
                selectionchange: this.onSongSelect
            }
        });

        // Listen for an application wide event
        this.application.on({
            stationstart: this.onStationStart, 
                scope: this
        });
    },
    ....
    onStationStart: function(station) {
        console.info('I called to inform you that the Station controller select box just has been changed');
        console.info('Now what do you want to do next?');
    },
}

如果选择框已更改,我们现在还会在控制器中触发该功能...onStationStartSong

来自煎茶文档:

应用程序事件对于具有许多控制器的事件非常有用。不是侦听每个控制器中的同一视图事件,而是只有一个控制器侦听视图事件并触发其他控制器可以侦听的应用程序范围事件。这也允许控制器在不知道或依赖彼此存在的情况下相互通信。

在我的情况下:单击树节点以更新网格面板中的数据。

更新2016感谢以下评论@gm2008:

在触发应用程序范围的自定义事件方面,在发布 ExtJS V5.1 之后,现在有一个新方法,它正在使用 。Ext.GlobalEvents

触发事件时,您可以呼叫:Ext.GlobalEvents.fireEvent('custom_event');

注册事件的处理程序时,调用:Ext.GlobalEvents.on('custom_event', function(arguments){/* handler codes*/}, scope);

此方法不限于控制器。任何组件都可以通过将组件对象作为输入参数范围来处理自定义事件。

发现于 Sencha Docs: MVC Part 2