Explicar a manipulação de eventos do ExtJS 4

130

Recentemente, comecei a aprender ExtJS e tenho problemas para entender como lidar com eventos. Não tenho experiência com nenhuma versão anterior do ExtJS.

Ao ler vários manuais, guias e páginas de documentação, descobri como usá-lo, mas não sei ao certo como funciona. Encontrei vários tutoriais para versões mais antigas do ExtJS, mas não tenho certeza de como eles são aplicáveis ​​no ExtJS 4.

Eu estou olhando especificamente para a "palavra final" em coisas como

  • Quais argumentos uma função de manipulação de eventos é passada? Existe um conjunto padrão de argumentos que sempre são aprovados?
  • como definir eventos personalizados para componentes personalizados que escrevemos? como podemos disparar esses eventos personalizados?
  • o valor de retorno (verdadeiro / falso) afeta como o evento borbulha? Caso contrário, como podemos controlar o evento borbulhando de dentro ou de fora do manipulador de eventos?
  • existe uma maneira padrão de registrar ouvintes de eventos? (Encontrei duas maneiras diferentes até agora e não sei por que cada método foi usado).

Por exemplo, essa pergunta me leva a acreditar que um manipulador de eventos pode receber alguns argumentos. Eu já vi outros tutoriais em que existem apenas dois argumentos para o manipulador. O que muda?

jrharshath
fonte
2
Só notei ... fora de tópico?
Jrharshath
12
88 Votos positivos sobre a questão, 155 votos positivos na primeira resposta e o grande e poderoso Andrew decide que este não está em questão. Viagem de poder grave acontecendo!
boatcoder 4/09/14
3
Votei em reabrir esta pergunta, pois as respostas aqui são uma mina de ouro. Eu editei a pergunta para melhor encaixar no estilo Q e A.
dbrin
1
Por favor, abra esta pergunta novamente, porque é realmente uma pergunta útil e genuína. tão cegamente não podemos fechá-lo.
Piyush Dholariya
2
Esta é uma pergunta bem formulada, e não vejo razão para fechá-la. Chamar esse tópico de fora é ridículo. Votou para reabrir.
Mike Fuchs

Respostas:

222

Vamos começar descrevendo a manipulação de eventos dos elementos DOM.

Tratamento de eventos do nó DOM

Antes de tudo, você não gostaria de trabalhar diretamente com o nó DOM. Em vez disso, você provavelmente desejaria utilizar a Ext.Elementinterface. Com o objetivo de atribuir manipuladores de eventos, Element.addListenere Element.on(estes são equivalentes) foram criados. Então, por exemplo, se tivermos html:

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

e queremos adicionar clickmanipulador de eventos.
Vamos recuperar Element:

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

Agora vamos verificar a documentação para o clickevento. Seu manipulador pode ter três parâmetros:

clique em (Ext.EventObject e, HTMLElement t, Object eOpts)

Conhecendo tudo isso, podemos atribuir manipulador:

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

Manipulação de evento de widgets

A manipulação de eventos de widgets é muito semelhante à manipulação de eventos de nós DOM.

Primeiro, a manipulação de eventos dos widgets é realizada utilizando o Ext.util.Observablemixin. Para lidar com os eventos corretamente, seu widget deve conter Ext.util.Observableum mixin. Todos os widgets integrados (como Painel, Formulário, Árvore, Grade, ...) têm Ext.util.Observablecomo combinação por padrão.

Para widgets, existem duas maneiras de atribuir manipuladores. O primeiro - é usar no método (ou addListener). Vamos, por exemplo, criar um Buttonwidget e atribuir um clickevento a ele. Antes de tudo, verifique os documentos do evento para obter os argumentos do manipulador:

clique (botão Ext.Button this, Event e, Object eOpts)

Agora vamos usar 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);
});

A segunda maneira é usar a configuração de listeners do 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);
    }
  }
});

Observe que o Buttonwidget é um tipo especial de widget. O evento Click pode ser atribuído 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);
  }
});

Disparo de eventos personalizados

Antes de tudo, você precisa registrar um evento usando o método addEvents :

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

O uso do addEventsmétodo é opcional. Conforme comentam esse método, não há necessidade de usar esse método, mas fornece lugar para a documentação dos eventos.

Para disparar seu evento, use o método fireEvent :

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

arg1, arg2, arg3, /* ... */será passado para o manipulador. Agora podemos lidar com seu evento:

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

Vale ressaltar que o melhor local para inserir a chamada do método addEvents é o initComponentmétodo do widget quando você está definindo um novo 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 */ });

Evitando bolhas de eventos

Para evitar bolhas, você pode return falseou usar Ext.EventObject.preventDefault(). Para impedir a ação padrão do navegador, use Ext.EventObject.stopPropagation().

Por exemplo, vamos atribuir o manipulador de eventos click ao nosso botão. E se não clicar no botão esquerdo, impeça a ação padrão do navegador:

myButton.on('click', function(btn, e){
  if (e.button !== 0)
    e.preventDefault();
});
Molecular Man
fonte
3
isso é ganância, mas existe alguma maneira de fazer a coisa "addEvents" através de alguma configuração? :)
jrharshath
@jrharshath, até onde eu sei, infelizmente, não há como fazer isso via config.
Molecular Man
como alguém cria esses -sysevice1 ', vejo que você os anexou e manipulou, mas como os criamos?
Heynow
1
Resposta brilhante! Eu sou novo no ExtJs e estava procurando uma maneira de referenciar qualquer elemento da página e usar manipuladores de eventos, como o jQuery. Você me ensinou a! Obrigado!
Rutwick Gangurde
1
pequeno erro na seção "Prevenção de bolhas de eventos". stopPropagation é usado para impedir a publicação de eventos e preventDefault é usado para impedir o comportamento / ação padrão.
MatRt
44

Acionando eventos abrangentes do aplicativo

Como fazer com que os controladores conversem entre si ...

Além da excelente resposta acima, quero mencionar eventos abrangentes do aplicativo, que podem ser muito úteis em uma configuração do MVC para permitir a comunicação entre controladores. (extjs4.1)

Digamos que temos uma estação controladora (exemplos do Sencha MVC) com uma caixa de seleção:

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

Quando a caixa de seleção aciona um evento de alteração, a função onStationSelecté acionada.

Dentro dessa função, vemos:

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

Isso cria e dispara um evento amplo do aplicativo que podemos ouvir de qualquer outro controlador.

Assim, em outro controlador, agora podemos saber quando a caixa de seleção da estação foi alterada. Isso é feito ouvindo o this.application.onseguinte:

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

Se a caixa de seleção foi alterada, agora também acionamos a função onStationStartno controlador Song...

Dos documentos do Sencha:

Eventos de aplicativo são extremamente úteis para eventos que possuem muitos controladores. Em vez de escutar o mesmo evento de exibição em cada um desses controladores, apenas um controlador escuta o evento de exibição e dispara um evento para todo o aplicativo que os outros podem ouvir. Isso também permite que os controladores se comuniquem sem conhecer ou depender da existência um do outro.

No meu caso: Clicar em um nó de árvore para atualizar dados em um painel de grade.

Atualize 2016 graças a @ gm2008 a partir dos comentários abaixo:

Em termos de acionamento de eventos personalizados em todo o aplicativo, agora existe um novo método após a publicação do ExtJS V5.1 , que está sendo usado Ext.GlobalEvents.

Ao disparar eventos, você pode ligar para: Ext.GlobalEvents.fireEvent('custom_event');

Ao registrar um manipulador do evento, você chama: Ext.GlobalEvents.on('custom_event', function(arguments){/* handler codes*/}, scope);

Este método não está limitado aos controladores. Qualquer componente pode manipular um evento personalizado colocando o objeto de componente como o escopo do parâmetro de entrada.

Encontrado no Sencha Docs: MVC Parte 2

mahatmanich
fonte
1
Em termos de acionamento de eventos personalizados em todo o aplicativo, agora existe um novo método após a publicação do ExtJS V5.1, que está usando o Ext.GlobalEvents. Quando você aciona um evento, você liga Ext.GlobalEvents.fireEvent('custom_event');Quando você registra um manipulador do evento, liga Ext.GlobalEvents.on('custom_event', function(arguments){/* handler codes*/}, scope};Aqui está um violino . Este método não está limitado aos controladores. Qualquer componente pode manipular um evento personalizado colocando o objeto de componente como parâmetro de entrada scope. A questão deve ser reaberta.
gm2008
15

Mais um truque para os ouvintes de eventos do controlador.

Você pode usar curingas para assistir a um evento de qualquer componente:

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

Só queria acrescentar um pouco de importância às excelentes respostas acima: Se você está trabalhando no Extjs 4.1 e não possui eventos abrangentes de aplicativos, mas precisa deles, estou usando uma técnica muito simples que pode ajudar: objeto simples estendendo o Observable e defina todos os eventos de aplicativo necessários. Em seguida, você pode disparar esses eventos de qualquer lugar no seu aplicativo, incluindo o elemento dom html real e ouvi-los a partir de qualquer componente, retransmitindo os elementos necessários desse componente.

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

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

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

Então você pode, de qualquer outro componente:

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

E dispare-os a partir de qualquer componente ou elemento dom:

 MessageBus.fireEvent('event1', somearg);

 <input type="button onclick="MessageBus.fireEvent('event2', 'somearg')">
Harel
fonte
Apenas para informação, this.addEvents foi descontinuado a partir do EXT JS 5.0. Portanto, não há necessidade de adicionar eventos agora
Ajay Sharma
11

Apenas mais duas coisas que achei úteis saber, mesmo que não façam parte da pergunta, realmente.

Você pode usar o relayEventsmétodo para instruir um componente a escutar determinados eventos de outro componente e, em seguida, acioná-los novamente como se fossem originários do primeiro componente. Os documentos da API fornecem o exemplo de uma grade que retransmite o loadevento da loja . É bastante útil ao escrever componentes personalizados que encapsulem vários subcomponentes.

Por outro lado, ou seja, passar eventos recebidos por um componente encapsulante mycmppara um de seus subcomponentes subcmp, pode ser feito assim

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