web-dev-qa-db-fra.com

Expliquer la gestion des événements ExtJS 4

J'ai récemment commencé à apprendre ExtJS et j'ai du mal à comprendre comment gérer les événements. Je n'ai aucune expérience des versions précédentes d'ExtJS.

En lisant divers manuels, guides et pages de documentation, j'ai compris comment l'utiliser, mais je ne comprends pas très bien comment cela fonctionne. J'ai trouvé plusieurs tutoriels pour les anciennes versions d'ExtJS, mais je ne suis pas certain de leur applicabilité dans ExtJS 4.

Je cherche spécifiquement sur le "dernier mot" sur des choses comme

  • quels arguments une fonction de gestion d'événements est-elle transmise? Existe-t-il un ensemble d'arguments standard toujours adopté?
  • comment définir des événements personnalisés pour les composants personnalisés que nous écrivons? Comment pouvons-nous déclencher ces événements personnalisés?
  • la valeur de retour (true/false) affecte-t-elle la manière dont l'événement bouillonne? Si ce n'est pas le cas, comment pouvons-nous contrôler les événements émanant de l'intérieur ou de l'extérieur du gestionnaire d'événements?
  • existe-t-il un moyen standard d’enregistrer les auditeurs d’événements? (J'ai rencontré deux manières différentes jusqu'à maintenant et je ne sais pas pourquoi chaque méthode a été utilisée).

Par exemple, cette question m'amène à penser qu'un gestionnaire d'événements peut recevoir pas mal d'arguments. J'ai vu d'autres tutoriels où il n'y a que deux arguments pour le gestionnaire. Quels changements?

127
jrharshath

Commençons par décrire la gestion des événements des éléments DOM.

Gestion des événements du noeud DOM

Tout d'abord, vous ne voudriez pas travailler directement avec le nœud DOM. Au lieu de cela, vous voudrez probablement utiliser l'interface Ext.Element . Dans le but d’affecter des gestionnaires d’événements, Element.addListener et Element.on (ils sont équivalents) ont été créés. Donc, par exemple, si nous avons du HTML:

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

et nous voulons ajouter click gestionnaire d'événements.
Récupérons Element:

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

Vérifions maintenant la documentation pour l'événement click . Son gestionnaire peut avoir trois paramètres:

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

Connaissant tout cela, nous pouvons affecter un gestionnaire:

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

Gestion des événements de widgets

La gestion des événements par les widgets est assez similaire à la gestion des événements par les nœuds DOM.

Tout d'abord, la gestion des événements de widgets est réalisée en utilisant Ext.util.Observable mixin. Pour gérer correctement les événements, votre widget doit contenir Ext.util.Observable Sous forme de mix. Tous les widgets intégrés (tels que Panneau, Formulaire, Arbre, Grille, ...) ont par défaut Ext.util.Observable.

Pour les widgets, il existe deux manières d'affecter des gestionnaires. La première consiste à utiliser la méthode on (ou addListener). Créons par exemple le widget Button et lui affectons l'événement click. Tout d'abord, vous devriez vérifier la documentation de l'événement pour les arguments du gestionnaire:

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

Maintenant, utilisons 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 deuxième méthode consiste à utiliser le widget listeners config:

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

Notez que le widget Button est un type spécial de widgets. L'événement de clic peut être assigné à ce widget en utilisant handler config:

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

Tir des événements personnalisés

Tout d’abord, vous devez enregistrer un événement en utilisant la méthode addEvents :

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

L'utilisation de la méthode addEvents est facultative. Comme les commentaires à cette méthode indiquent qu'il n'est pas nécessaire d'utiliser cette méthode, elle fournit un emplacement pour la documentation des événements.

Pour déclencher votre événement, utilisez la méthode fireEvent :

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

arg1, arg2, arg3, /* ... */ Sera passé dans le gestionnaire. Maintenant, nous pouvons gérer votre événement:

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

Il est à noter que le meilleur endroit pour insérer addEvents l'appel de méthode est la méthode initComponent du widget lorsque vous définissez un nouveau 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 */ });

Prévention de la propagation d'événements

Pour empêcher la formation de bulles, vous pouvez return false Ou utiliser Ext.EventObject.preventDefault() . Pour éviter l'action par défaut du navigateur, utilisez Ext.EventObject.stopPropagation() .

Par exemple, assignons le gestionnaire d’événements clic à notre bouton. Et si ce n'est pas parti, le bouton a été cliqué pour empêcher l'action du navigateur par défaut

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

Activation d'événements au niveau de l'application

Comment faire en sorte que les contrôleurs se parlent ...

En plus de la très bonne réponse ci-dessus, je souhaite mentionner les événements à l'échelle de l'application qui peuvent être très utiles dans une configuration MVC pour permettre la communication entre les contrôleurs. (extjs4.1)

Disons que nous avons une station de contrôle (exemples Sencha MVC) avec une boîte de sélection:

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

Lorsque la zone de sélection déclenche un événement de modification, la fonction onStationSelect est déclenchée.

Dans cette fonction, nous voyons:

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

Cela crée et déclenche un événement à l'échelle de l'application que nous pouvons écouter à partir de tout autre contrôleur.

Ainsi, dans un autre contrôleur, nous pouvons maintenant savoir quand la boîte de sélection de station a été modifiée. Cela se fait en écoutant this.application.on Comme suit:

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 la selectbox a été modifiée, nous activons maintenant la fonction onStationStart dans le contrôleur Song également ...

D'après la documentation Sencha:

Les événements d'application sont extrêmement utiles pour les événements comportant de nombreux contrôleurs. Au lieu d'écouter le même événement d'affichage dans chacun de ces contrôleurs, un seul contrôleur écoute l'événement d'affichage et déclenche un événement à l'échelle de l'application que les autres peuvent écouter. Cela permet également aux contrôleurs de communiquer les uns avec les autres sans se rendre compte de l’existence de chacun ou dépendre de celle-ci.

Dans mon cas: cliquer sur un nœud d’arbre pour mettre à jour les données dans un panneau de grille.

Mise à jour 2016 grâce à @ gm2008 à partir des commentaires ci-dessous:

En termes de déclenchement d'événements personnalisés à l'échelle de l'application, il existe une nouvelle méthode maintenant après la publication de ExtJS V5.1 , qui utilise Ext.GlobalEvents.

Lorsque vous déclenchez des événements, vous pouvez appeler: Ext.GlobalEvents.fireEvent('custom_event');

Lorsque vous enregistrez un gestionnaire de l'événement, vous appelez: Ext.GlobalEvents.on('custom_event', function(arguments){/* handler codes*/}, scope);

Cette méthode n'est pas limitée aux contrôleurs. Tout composant peut gérer un événement personnalisé en plaçant l'objet composant en tant que portée du paramètre d'entrée.

trouvé dans Sencha Docs: MVC Part 2

43
mahatmanich

Une astuce supplémentaire pour les auditeurs d'événements du contrôleur.

Vous pouvez utiliser des caractères génériques pour surveiller un événement à partir de n'importe quel composant:

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

Je voulais juste ajouter quelques sous aux excellentes réponses ci-dessus: Si vous travaillez sur des versions antérieures à Extjs 4.1 et que vous n'avez pas d'événements à l'échelle de l'application mais que vous en avez besoin, j'ai utilisé une technique très simple qui pourrait vous aider: Créer une objet simple étendant Observable et définissez tous les événements d’application dont vous pourriez avoir besoin. Vous pouvez ensuite déclencher ces événements à partir de n’importe où dans votre application, y compris d’un élément html dom réel, et les écouter depuis n’importe quel composant en relayant les éléments requis à partir de ce composant.

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

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

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

Ensuite, vous pouvez, à partir de tout autre composant:

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

Et tirez-les depuis n'importe quel composant ou élément dom:

 MessageBus.fireEvent('event1', somearg);

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

Juste deux autres choses que j'ai trouvé utiles de savoir, même si elles ne font pas partie de la question, vraiment.

Vous pouvez utiliser la méthode relayEvents pour demander à un composant d'écouter certains événements d'un autre composant, puis de les réexécuter comme s'ils provenaient du premier composant. Les documents de l'API donnent l'exemple d'une grille relayant l'événement store load. C'est très pratique lorsque vous écrivez des composants personnalisés qui encapsulent plusieurs sous-composants.

Inversement, c’est-à-dire transmettre les événements reçus par un composant encapsulant mycmp à l’un de ses sous-composants subcmp, peut être fait comme ceci

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