Javascript 解释 ExtJS 4 事件处理

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7260134/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 01:31:24  来源:igfitidea点击:

Explain ExtJS 4 event handling

javascriptextjsevent-handlingextjs4

提问by jrharshath

I've recently started learning ExtJS, and have trouble understanding how to handle Events. I have no experience of any previous versions of ExtJS.

我最近开始学习 ExtJS,但无法理解如何处理事件。我没有任何以前版本的 ExtJS 的经验。

From reading various manuals, guides and documentation pages, I've figured out how to use it, but I'm not clear on how it works. I've found several tutorials for older versions of ExtJS, but I'm not sure how applicable they are in ExtJS 4.

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

I'm specifically looking on the "final word" on things like

我特别关注诸如此类的“最后一句话”

  • what arguments does an event handling function get passed? Is there a standard set of args that always get passed?
  • how to define custom events for custom components we write? how can we fire these custom event?
  • does the return value (true/false) affect how the event bubbles? If not, how can we control event bubbling from within, or outside of the event handler?
  • is there a standard way to register event listeners? (I've come across two different ways til now, and I'm not sure why each method was used).
  • 事件处理函数传递了哪些参数?是否有一组标准的参数总是被通过?
  • 如何为我们编写的自定义组件定义自定义事件?我们如何触发这些自定义事件?
  • 返回值 (true/false) 是否会影响事件冒泡的方式?如果没有,我们如何控制事件处理程序内部或外部的事件冒泡?
  • 是否有注册事件侦听器的标准方法?(到目前为止,我遇到了两种不同的方法,我不确定为什么使用每种方法)。

For example, this questionleads me to believe that an event handler can receive quite a few arguments. I've seen other tutorials where there are just two arguments to the handler. What changes?

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

回答by Molecular Man

Let's start by describing DOM elements' event handling.

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

DOM node event handling

DOM 节点事件处理

First of all you wouldn't want to work with DOM node directly. Instead you probably would want to utilize Ext.Elementinterface. For the purpose of assigning event handlers, Element.addListenerand Element.on(these are equivalent) were created. So, for example, if we have html:

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

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

and we want add clickevent handler.
Let's retrieve Element:

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

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

Now let's check docs for clickevent. It's handler may have three parameters:

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

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

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

Knowing all this stuff we can assign handler:

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

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

Widgets event handling

小部件事件处理

Widgets event handling is pretty much similar to DOM nodes event handling.

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

First of all, widgets event handling is realized by utilizing Ext.util.Observablemixin. In order to handle events properly your widget must containg Ext.util.Observableas a mixin. All built-in widgets (like Panel, Form, Tree, Grid, ...) has Ext.util.Observableas a mixin by default.

首先,widgets的事件处理是利用Ext.util.Observablemixin实现的。为了正确处理事件,您的小部件必须包含Ext.util.Observable作为 mixin。Ext.util.Observable默认情况下,所有内置小部件(如 Panel、Form、Tree、Grid 等)都作为 mixin。

For widgets there are two ways of assigning handlers. The first one - is to use onmethod (or addListener). Let's for example create Buttonwidget and assign clickevent to it. First of all you should check event's docs for handler's arguments:

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

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

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

Now let's use on:

现在让我们使用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);
});

The second way is to use widget's listenersconfig:

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

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

Notice that Buttonwidget is a special kind of widgets. Click event can be assigned to this widget by using handlerconfig:

请注意,Button小部件是一种特殊的小部件。单击事件可以通过使用handler配置分配给这个小部件:

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

Custom events firing

自定义事件触发

First of all you need to register an event using addEventsmethod:

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

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

Using the addEventsmethod is optional. As comments to this method say there is no need to use this method but it provides place for events documentation.

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

To fire your event use fireEventmethod:

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

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

arg1, arg2, arg3, /* ... */will be passed into handler. Now we can handle your event:

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

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

It's worth mentioning that the best place for inserting addEventsmethod call is widget's initComponentmethod when you are defining new widget:

值得一提的是,在定义新小部件时,插入addEvents方法调用的最佳位置是小部件的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 */ });

Preventing event bubbling

防止事件冒泡

To prevent bubbling you can return falseor use Ext.EventObject.preventDefault(). In order to prevent browser's default action use Ext.EventObject.stopPropagation().

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

For example let's assign click event handler to our button. And if not left button was clicked prevent default browser action:

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

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

回答by mahatmanich

Firing application wide events

触发应用程序范围的事件

How to make controllers talk to each other ...

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

In addition to the very great answer above I want to mention application wide events which can be very useful in an MVC setup to enable communication between controllers. (extjs4.1)

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

Lets say we have a controller Station (Sencha MVC examples) with a select box:

假设我们有一个带有选择框的控制器 Station(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]);
    },    
   ...
});

When the select box triggers a change event, the function onStationSelectis fired.

When the select box triggers a change event, the function onStationSelectis fired.

Within that function we see:

在该函数中,我们看到:

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

This creates and fires an application wide event that we can listen to from any other controller.

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

Thus in another controller we can now know when the station select box has been changed. This is done through listening to this.application.onas follows:

因此,在另一个控制器中,我们现在可以知道站点选择框何时被更改。这是通过收听完成的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?');
    },
}

If the selectbox has been changed we now fire the function onStationStartin the controller Songalso ...

如果选择框已更改,我们现在也触发onStationStart控制器中的功能Song......

From the Sencha docs:

从 Sencha 文档:

Application events are extremely useful for events that have many controllers. Instead of listening for the same view event in each of these controllers, only one controller listens for the view event and fires an application-wide event that the others can listen for. This also allows controllers to communicate with one another without knowing about or depending on each other's existence.

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

In my case: Clicking on a tree node to update data in a grid panel.

就我而言:单击树节点以更新网格面板中的数据。

Update 2016 thanks to @gm2008 from the comments below:

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

In terms of firing application-wide custom events, there is a new method now after ExtJS V5.1is published, which is using Ext.GlobalEvents.

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

When you fire events, you can call: Ext.GlobalEvents.fireEvent('custom_event');

当您触发事件时,您可以调用: Ext.GlobalEvents.fireEvent('custom_event');

When you register a handler of the event, you call: Ext.GlobalEvents.on('custom_event', function(arguments){/* handler codes*/}, scope);

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

This method is not limited to controllers. Any component can handle a custom event through putting the component object as the input parameter scope.

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

Found in Sencha Docs: MVC Part 2

在 Sencha Docs: MVC Part 2 中找到

回答by dbrin

One more trick for controller event listeners.

控制器事件侦听器的另一个技巧。

You can use wildcards to watch for an event from any component:

您可以使用通配符来监视来自任何组件的事件:

this.control({
   '*':{ 
       myCustomEvent: this.doSomething
   }
});

回答by Harel

Just wanted to add a couple of pence to the excellent answers above: If you are working on pre Extjs 4.1, and don't have application wide events but need them, I've been using a very simple technique that might help: Create a simple object extending Observable, and define any app wide events you might need in it. You can then fire those events from anywhere in your app, including actual html dom element and listen to them from any component by relaying the required elements from that component.

只是想为上面的优秀答案添加几便士:如果您正在使用 Extjs 4.1 之前的版本,并且没有应用程序范围的事件但需要它们,我一直在使用一种可能有帮助的非常简单的技术:创建一个扩展 Observable 的简单对象,并在其中定义您可能需要的任何应用程序范围的事件。然后,您可以从应用程序的任何位置触发这些事件,包括实际的 html dom 元素,并通过从该组件中继所需元素来从任何组件监听它们。

Ext.define('Lib.MessageBus', {
    extend: 'Ext.util.Observable',

    constructor: function() {
        this.addEvents(
            /*
             * describe the event
             */
                  "eventname"

            );
        this.callParent(arguments);
    }
});

Then you can, from any other component:

然后,您可以从任何其他组件:

 this.relayEvents(MesageBus, ['event1', 'event2'])

And fire them from any component or dom element:

并从任何组件或 dom 元素触发它们:

 MessageBus.fireEvent('event1', somearg);

 <input type="button onclick="MessageBus.fireEvent('event2', 'somearg')">

回答by blahgonaut

Just two more things I found helpful to know, even if they are not part of the question, really.

还有两件事我觉得很有帮助,即使它们不是问题的一部分,真的。

You can use the relayEventsmethod to tell a component to listen for certain events of another component and then fire them again as if they originate from the first component. The API docs give the example of a grid relaying the store loadevent. It is quite handy when writing custom components that encapsulate several sub-components.

您可以使用该relayEvents方法告诉组件侦听另一个组件的某些事件,然后再次触发它们,就好像它们源自第一个组件一样。API 文档给出了中继存储load事件的网格示例。在编写封装多个子组件的自定义组件时非常方便。

The other way around, i.e. passing on events received by an encapsulating component mycmpto one of its sub-components subcmp, can be done like this

另一种方式,mycmp即将封装组件接收到的事件传递给它的一个子组件subcmp,可以这样完成

mycmp.on('show' function (mycmp, eOpts)
{
   mycmp.subcmp.fireEvent('show', mycmp.subcmp, eOpts);
});