Explicar el manejo de eventos ExtJS 4

130

Recientemente comencé a aprender ExtJS y tengo problemas para entender cómo manejar los eventos. No tengo experiencia en ninguna versión anterior de ExtJS.

Al leer varios manuales, guías y páginas de documentación, descubrí cómo usarlo, pero no tengo claro cómo funciona. He encontrado varios tutoriales para versiones anteriores de ExtJS, pero no estoy seguro de cuán aplicables sean en ExtJS 4.

Estoy buscando específicamente la "palabra final" en cosas como

  • ¿Qué argumentos pasa una función de manejo de eventos? ¿Existe un conjunto estándar de argumentos que siempre se pasan?
  • ¿Cómo definir eventos personalizados para los componentes personalizados que escribimos? ¿Cómo podemos disparar estos eventos personalizados?
  • ¿El valor de retorno (verdadero / falso) afecta cómo burbujea el evento? Si no, ¿cómo podemos controlar el burbujeo de eventos desde dentro o fuera del controlador de eventos?
  • ¿Hay alguna forma estándar de registrar oyentes de eventos? (Me he encontrado con dos formas diferentes hasta ahora, y no estoy seguro de por qué se utilizó cada método).

Por ejemplo, esta pregunta me lleva a creer que un controlador de eventos puede recibir bastantes argumentos. He visto otros tutoriales donde solo hay dos argumentos para el controlador. ¿Que cambios?

jrharshath
fuente
2
Acabo de notar ... fuera de tema?
jrharshath
12
88 votos a favor sobre la pregunta, 155 votos a favor en la primera respuesta y el gran y poderoso Andrew decide que esta está fuera de tema. ¡Se está produciendo un grave viaje de poder!
Boatcoder
3
He votado para volver a abrir esta pregunta ya que las respuestas aquí son una mina de oro. He editado la pregunta para que se ajuste mejor al estilo Q y A.
dbrin
1
Abra esta pregunta nuevamente porque es realmente útil y una pregunta genuina. así que ciegamente no podemos cerrarlo.
Piyush Dholariya
2
Esta es una pregunta bien redactada, y no veo ninguna razón para cerrarla. Llamar a esto fuera de tema es ridículo. Votado para reabrir.
Mike Fuchs

Respuestas:

222

Comencemos describiendo el manejo de eventos de los elementos DOM.

Manejo de eventos del nodo DOM

En primer lugar, no querrá trabajar con el nodo DOM directamente. En cambio, es probable que desee utilizar la Ext.Elementinterfaz. Con el fin de asignar controladores de eventos, Element.addListenery Element.on(estos son equivalentes) fueron creados. Entonces, por ejemplo, si tenemos html:

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

y queremos agregar clickcontrolador de eventos.
Recuperemos Element:

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

Ahora revisemos los documentos para el clickevento. Su controlador puede tener tres parámetros:

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

Sabiendo todo esto, podemos asignar un controlador:

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

Manejo de eventos de widgets

El manejo de eventos de widgets es bastante similar al manejo de eventos de nodos DOM.

En primer lugar, el manejo de eventos de widgets se realiza utilizando Ext.util.Observablemixin. Para manejar los eventos correctamente, su widget debe contactarse Ext.util.Observablecomo un mixin. Todos los widgets integrados (como Panel, Formulario, Árbol, Cuadrícula, ...) tienen Ext.util.Observableuna combinación por defecto.

Para los widgets hay dos formas de asignar controladores. El primero es usar el método (o addListener). Vamos a crear, por ejemplo, un Buttonwidget y asignarle un clickevento. En primer lugar, debe consultar los documentos del evento para ver los argumentos del manejador:

Haga clic en (botón ext., botón este, evento e, objetos e)

Ahora usemos 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);
});

La segunda forma es usar la configuración de escuchas del widget :

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

Tenga en cuenta que el Buttonwidget es un tipo especial de widgets. El evento de clic se puede asignar a este widget usando handlerconfig:

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

Eventos personalizados disparando

En primer lugar, debe registrar un evento utilizando el método addEvents :

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

Usar el addEventsmétodo es opcional. Como los comentarios a este método dicen que no hay necesidad de usar este método, pero proporciona lugar para la documentación de eventos.

Para activar su evento use el método fireEvent :

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

arg1, arg2, arg3, /* ... */será pasado al controlador. Ahora podemos manejar su evento:

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

Vale la pena mencionar que el mejor lugar para insertar la llamada al método addEvents es el initComponentmétodo del widget cuando se define un nuevo widget:

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 */ });

Prevenir eventos burbujeantes

Para evitar el burbujeo, puedes return falseo usar Ext.EventObject.preventDefault(). Para evitar el uso de acción predeterminada del navegador Ext.EventObject.stopPropagation().

Por ejemplo, asignemos un controlador de eventos de clic a nuestro botón. Y si no se hizo clic en el botón izquierdo, evite la acción predeterminada del navegador:

myButton.on('click', function(btn, e){
  if (e.button !== 0)
    e.preventDefault();
});
Hombre molecular
fuente
3
esto, es avaricia, pero ¿hay alguna forma de hacer lo "addEvents" a través de alguna configuración? :)
jrharshath
@jrharshath, por lo que sé, desafortunadamente, no hay forma de hacerlo a través de config.
Molecular Man
¿cómo se crean estos -'myspecialevent1 ', veo que los adjuntaste y manejaste pero cómo creamos estos?
heyNow
1
Respuesta brillante! Soy nuevo en ExtJs y estaba buscando una manera de hacer referencia a cualquier elemento en la página y usar controladores de eventos en ellos, al igual que jQuery. Me enseñaste a hacerlo! ¡Gracias!
Rutwick Gangurde
1
pequeño error en la sección "Prevención de burbujeo de eventos". stopPropagation se usa para evitar que el evento burbujee, y preventDefault se usa para evitar el comportamiento / acción predeterminado.
MatRt
44

Aplicación de disparos para eventos amplios

Cómo hacer que los controladores hablen entre sí ...

Además de la excelente respuesta anterior, quiero mencionar eventos de toda la aplicación que pueden ser muy útiles en una configuración MVC para permitir la comunicación entre controladores. (extjs4.1)

Digamos que tenemos una estación controladora (ejemplos de Sencha MVC) con un cuadro de selección:

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]);
    },    
   ...
});

Cuando el cuadro de selección desencadena un evento de cambio, se activa la función onStationSelect.

Dentro de esa función vemos:

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

Esto crea y dispara un evento de toda la aplicación que podemos escuchar desde cualquier otro controlador.

Por lo tanto, en otro controlador ahora podemos saber cuándo se ha cambiado el cuadro de selección de estación. Esto se hace escuchando this.application.onlo siguiente:

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?');
    },
}

Si se ha cambiado la casilla de selección, ahora activamos la función onStationStarten el controlador Songtambién ...

De los documentos de Sencha:

Los eventos de aplicación son extremadamente útiles para eventos que tienen muchos controladores. En lugar de escuchar el mismo evento de vista en cada uno de estos controladores, solo un controlador escucha el evento de vista y dispara un evento de toda la aplicación que los demás pueden escuchar. Esto también permite que los controladores se comuniquen entre sí sin conocer o depender de la existencia del otro.

En mi caso: hacer clic en un nodo de árbol para actualizar los datos en un panel de cuadrícula.

Actualización 2016 gracias a @ gm2008 de los comentarios a continuación:

En términos de disparar eventos personalizados para toda la aplicación, ahora hay un nuevo método después de que se publica ExtJS V5.1 , que está utilizando Ext.GlobalEvents.

Cuando disparas eventos, puedes llamar a: Ext.GlobalEvents.fireEvent('custom_event');

Cuando registra un controlador del evento, llama a: Ext.GlobalEvents.on('custom_event', function(arguments){/* handler codes*/}, scope);

Este método no se limita a los controladores. Cualquier componente puede manejar un evento personalizado colocando el objeto componente como el alcance del parámetro de entrada.

Encontrado en Sencha Docs: MVC Parte 2

mahatmanich
fuente
1
En términos de disparar eventos personalizados para toda la aplicación, ahora hay un nuevo método después de que se publica ExtJS V5.1, que utiliza Ext.GlobalEvents. Cuando disparas un evento, llamas Ext.GlobalEvents.fireEvent('custom_event');Cuando registras un controlador del evento, llamas Ext.GlobalEvents.on('custom_event', function(arguments){/* handler codes*/}, scope};Aquí hay un violín . Este método no se limita a los controladores. Cualquier componente puede manejar un evento personalizado colocando el objeto componente como parámetro de entrada scope. La pregunta debe reabrirse.
gm2008
15

Un truco más para los oyentes de eventos del controlador.

Puede usar comodines para ver un evento desde cualquier componente:

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

Solo quería agregar un par de peniques a las excelentes respuestas anteriores: si está trabajando en pre Extjs 4.1 y no tiene eventos para toda la aplicación pero los necesita, he estado utilizando una técnica muy simple que podría ayudar: crear un objeto simple que extiende Observable y define cualquier evento de aplicación que pueda necesitar en él. Luego puede disparar esos eventos desde cualquier parte de su aplicación, incluido el elemento dom html real y escucharlos desde cualquier componente retransmitiendo los elementos necesarios de ese componente.

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

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

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

Entonces puedes, desde cualquier otro componente:

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

Y dispararlos desde cualquier componente o elemento dom:

 MessageBus.fireEvent('event1', somearg);

 <input type="button onclick="MessageBus.fireEvent('event2', 'somearg')">
Harel
fuente
Solo para información, this.addEvents ha quedado en desuso a partir de EXT JS 5.0. Así que no hay necesidad de agregar eventos ahora
Ajay Sharma
11

Solo dos cosas más que encontré útiles para saber, incluso si no son parte de la pregunta, realmente.

Puede usar el relayEventsmétodo para decirle a un componente que escuche ciertos eventos de otro componente y luego dispararlos nuevamente como si se originaran en el primer componente. Los documentos API dan el ejemplo de una cuadrícula que retransmite el loadevento de la tienda . Es bastante útil al escribir componentes personalizados que encapsulan varios subcomponentes.

Al revés, es decir, transmitir eventos recibidos por un componente de encapsulación mycmpa uno de sus subcomponentes subcmp, se puede hacer así

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