Erläutern Sie die ExtJS 4-Ereignisbehandlung

130

Ich habe vor kurzem angefangen, ExtJS zu lernen, und habe Probleme, den Umgang mit Ereignissen zu verstehen. Ich habe keine Erfahrung mit früheren Versionen von ExtJS.

Durch das Lesen verschiedener Handbücher, Anleitungen und Dokumentationsseiten habe ich herausgefunden, wie man es verwendet, aber ich bin mir nicht sicher, wie es funktioniert. Ich habe mehrere Tutorials für ältere Versionen von ExtJS gefunden, bin mir aber nicht sicher, wie sie in ExtJS 4 anwendbar sind.

Ich schaue speziell auf das "letzte Wort" zu Dingen wie

  • Welche Argumente werden einer Ereignisbehandlungsfunktion übergeben? Gibt es einen Standardsatz von Argumenten, die immer übergeben werden?
  • Wie definiere ich benutzerdefinierte Ereignisse für benutzerdefinierte Komponenten, die wir schreiben? Wie können wir diese benutzerdefinierten Ereignisse auslösen?
  • Beeinflusst der Rückgabewert (wahr / falsch), wie das Ereignis sprudelt? Wenn nicht, wie können wir das Sprudeln von Ereignissen innerhalb oder außerhalb des Ereignishandlers steuern?
  • Gibt es eine Standardmethode zum Registrieren von Ereignis-Listenern? (Ich bin bis jetzt auf zwei verschiedene Arten gestoßen, und ich bin mir nicht sicher, warum jede Methode verwendet wurde).

Zum Beispiel dieser Frage führt mich zu glauben , dass ein Event - Handler schon einige Argumente empfangen können. Ich habe andere Tutorials gesehen, in denen der Handler nur zwei Argumente hat. Was ändert sich?

jrharshath
quelle
2
Gerade bemerkt ... nicht zum Thema?
Jrharshath
12
88 positive Stimmen für die Frage, 155 positive Stimmen für die erste Antwort und der große und mächtige Andrew entscheidet, dass diese Frage nicht zum Thema gehört. Ernsthafter Power Trip geht weiter!
Bootscodierer
3
Ich habe dafür gestimmt, diese Frage erneut zu öffnen, da die Antworten hier eine Goldmine sind. Ich habe die Frage bearbeitet, um sie besser an den Q- und A-Stil anzupassen.
Dbrin
1
Bitte öffnen Sie diese Frage erneut, da es sich um eine wirklich hilfreiche und echte Frage handelt. so blind können wir es nicht schließen.
Piyush Dholariya
2
Dies ist eine gut formulierte Frage, und ich sehe keinen Grund, sie zu schließen. Es ist lächerlich, dieses Thema abzubrechen. Für die Wiedereröffnung gestimmt.
Mike Fuchs

Antworten:

222

Beginnen wir mit der Beschreibung der Ereignisbehandlung von DOM-Elementen.

Behandlung von DOM-Knotenereignissen

Zunächst möchten Sie nicht direkt mit dem DOM-Knoten arbeiten. Stattdessen möchten Sie wahrscheinlich die Ext.ElementSchnittstelle verwenden. Zum Zuweisen von Ereignishandlern wurden Element.addListenerund Element.on(diese sind gleichwertig) erstellt. Also zum Beispiel, wenn wir HTML haben:

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

und wir wollen clickEvent-Handler hinzufügen .
Lassen Sie uns abrufen Element:

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

Lassen Sie uns nun die Dokumente auf clickEreignisse überprüfen . Der Handler kann drei Parameter haben:

Klicken Sie auf (Ext.EventObject e, HTMLElement t, Object eOpts).

Wenn wir all diese Dinge kennen, können wir den Handler zuweisen:

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

Widgets Ereignisbehandlung

Die Ereignisbehandlung von Widgets ist der Ereignisbehandlung von DOM-Knoten ziemlich ähnlich.

Zunächst wird die Ereignisbehandlung von Widgets Ext.util.Observablemithilfe von Mixin realisiert . Um Ereignisse richtig zu behandeln, muss Ihr Widget Ext.util.Observableals Mixin enthalten sein. Alle integrierten Widgets (wie Panel, Formular, Baum, Raster, ...) sind Ext.util.Observablestandardmäßig als Mixin enthalten.

Für Widgets gibt es zwei Möglichkeiten, Handler zuzuweisen. Die erste - ist auf Methode (oder addListener) zu verwenden. Lassen Sie uns zum Beispiel ein ButtonWidget erstellen und ihm ein clickEreignis zuweisen . Zunächst sollten Sie die Dokumente des Ereignisses auf die Argumente des Handlers überprüfen:

Klicken Sie auf (Ext.button.Button this, Event e, Object eOpts).

Verwenden wir nun 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);
});

Die zweite Möglichkeit besteht darin, die Listener- Konfiguration des Widgets zu verwenden :

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

Beachten Sie, dass ButtonWidget eine spezielle Art von Widgets ist. Klickereignis kann diesem Widget mithilfe von handlerconfig zugewiesen werden :

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

Benutzerdefinierte Ereignisse werden ausgelöst

Zunächst müssen Sie ein Ereignis mit der Methode addEvents registrieren :

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

Die Verwendung der addEventsMethode ist optional. Wie Kommentare zu dieser Methode besagen, muss diese Methode nicht verwendet werden, bietet jedoch Platz für die Dokumentation von Ereignissen.

Verwenden Sie die fireEvent- Methode, um Ihre Veranstaltung auszulösen :

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

arg1, arg2, arg3, /* ... */wird an den Handler übergeben. Jetzt können wir Ihre Veranstaltung abwickeln:

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

Es ist erwähnenswert, dass der beste Ort zum Einfügen des addEvents- Methodenaufrufs die Widget- initComponentMethode ist, wenn Sie ein neues Widget definieren:

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

Verhindern von Ereignisblasen

Um ein Sprudeln zu verhindern, können return falseoder verwenden Sie Ext.EventObject.preventDefault(). Um die Standardaktion des Browsers zu verhindern, verwenden Sie Ext.EventObject.stopPropagation().

Weisen Sie beispielsweise unserer Schaltfläche einen Klickereignishandler zu. Wenn nicht auf die linke Schaltfläche geklickt wurde, wird die Standardaktion des Browsers verhindert:

myButton.on('click', function(btn, e){
  if (e.button !== 0)
    e.preventDefault();
});
Molecular Man
quelle
3
Dies ist Gier, aber gibt es eine Möglichkeit, das "addEvents" -Ding über eine Konfiguration auszuführen? :)
jrharshath
@ jrharshath, soweit ich weiß, gibt es leider keine Möglichkeit, dies über config zu tun.
Molecular Man
Wie erstellt man diese -'myspecialevent1 ', ich sehe, Sie haben sie angehängt und behandelt, aber wie erstellen wir diese?
HeyNow
1
Geniale Antwort! Ich bin neu in ExtJs und habe nach einer Möglichkeit gesucht, auf ein Element auf der Seite zu verweisen und Event-Handler zu verwenden, genau wie bei jQuery. Du hast es mir beigebracht! Vielen Dank!
Rutwick Gangurde
1
kleiner Fehler im Abschnitt "Verhindern von Ereignisblasen". stopPropagation wird verwendet, um das Bubling von Ereignissen zu verhindern, und prepareDefault wird verwendet, um das Standardverhalten / die Standardaktion zu verhindern.
MatRt
44

Anwendungsweite Ereignisse auslösen

Wie man Controller dazu bringt, miteinander zu sprechen ...

Zusätzlich zu der oben sehr guten Antwort möchte ich anwendungsweite Ereignisse erwähnen, die in einem MVC-Setup sehr nützlich sein können, um die Kommunikation zwischen Controllern zu ermöglichen. (extjs4.1)

Nehmen wir an, wir haben eine Controller-Station (Sencha MVC-Beispiele) mit einem Auswahlfeld:

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

Wenn das Auswahlfeld ein Änderungsereignis auslöst, wird die Funktion onStationSelectausgelöst.

Innerhalb dieser Funktion sehen wir:

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

Dadurch wird ein anwendungsweites Ereignis erstellt und ausgelöst, das wir von jedem anderen Controller abhören können.

Somit können wir in einem anderen Controller jetzt wissen, wann das Stationsauswahlfeld geändert wurde. Dies geschieht durch Anhören this.application.onwie folgt:

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

Wenn die Auswahlbox geändert wurde, wird jetzt auch die Funktion onStationStartin der Steuerung ausgelöst Song...

Aus den Sencha-Dokumenten:

Anwendungsereignisse sind äußerst nützlich für Ereignisse mit vielen Controllern. Anstatt in jedem dieser Controller auf dasselbe Ansichtsereignis zu warten, wartet nur ein Controller auf das Ansichtsereignis und löst ein anwendungsweites Ereignis aus, auf das die anderen warten können. Dies ermöglicht es den Steuerungen auch, miteinander zu kommunizieren, ohne über die Existenz des anderen Bescheid zu wissen oder davon abhängig zu sein.

In meinem Fall: Klicken Sie auf einen Baumknoten, um die Daten in einem Rasterfeld zu aktualisieren.

Update 2016 dank @ gm2008 aus den Kommentaren unten:

In Bezug auf das Auslösen anwendungsweiter benutzerdefinierter Ereignisse gibt es jetzt nach der Veröffentlichung von ExtJS V5.1 eine neue Methode , die verwendet wird Ext.GlobalEvents.

Wenn Sie Ereignisse auslösen, können Sie Folgendes aufrufen: Ext.GlobalEvents.fireEvent('custom_event');

Wenn Sie einen Handler des Ereignisses registrieren, rufen Sie Folgendes auf: Ext.GlobalEvents.on('custom_event', function(arguments){/* handler codes*/}, scope);

Diese Methode ist nicht auf Controller beschränkt. Jede Komponente kann ein benutzerdefiniertes Ereignis verarbeiten, indem das Komponentenobjekt als Eingabeparameterbereich festgelegt wird.

Gefunden in Sencha Docs: MVC Part 2

Mahatmanich
quelle
1
In Bezug auf das Auslösen anwendungsweiter benutzerdefinierter Ereignisse gibt es jetzt nach der Veröffentlichung von ExtJS V5.1 eine neue Methode, die Ext.GlobalEvents verwendet. Wenn Sie ein Ereignis auslösen, rufen Sie an. Ext.GlobalEvents.fireEvent('custom_event');Wenn Sie einen Handler des Ereignisses registrieren, rufen Sie an. Ext.GlobalEvents.on('custom_event', function(arguments){/* handler codes*/}, scope};Hier ist eine Geige . Diese Methode ist nicht auf Controller beschränkt. Jede Komponente kann ein benutzerdefiniertes Ereignis verarbeiten, indem das Komponentenobjekt als Eingabeparameter festgelegt wird scope. Die Frage sollte erneut geöffnet werden.
gm2008
15

Ein weiterer Trick für Controller-Ereignis-Listener.

Sie können Platzhalter verwenden, um von einer beliebigen Komponente aus nach einem Ereignis zu suchen:

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

Ich wollte nur ein paar Pence zu den hervorragenden Antworten oben hinzufügen: Wenn Sie an Pre Extjs 4.1 arbeiten und keine anwendungsweiten Ereignisse haben, diese aber benötigen, habe ich eine sehr einfache Technik verwendet, die helfen könnte: Erstellen Sie eine einfaches Objekt, das Observable erweitert, und definieren Sie alle app-weiten Ereignisse, die Sie möglicherweise darin benötigen. Sie können diese Ereignisse dann von einer beliebigen Stelle in Ihrer App aus auslösen, einschließlich des tatsächlichen HTML-Dom-Elements, und sie von einer beliebigen Komponente abhören, indem Sie die erforderlichen Elemente von dieser Komponente weiterleiten.

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

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

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

Dann können Sie aus jeder anderen Komponente:

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

Und feuern Sie sie von jeder Komponente oder jedem dom-Element ab:

 MessageBus.fireEvent('event1', somearg);

 <input type="button onclick="MessageBus.fireEvent('event2', 'somearg')">
Harel
quelle
Nur zur Information, this.addEvents ist ab EXT JS 5.0 veraltet. Es ist also nicht nötig, jetzt Ereignisse hinzuzufügen
Ajay Sharma
11

Nur noch zwei Dinge, die ich hilfreich fand, auch wenn sie nicht wirklich Teil der Frage sind.

Mit dieser relayEventsMethode können Sie eine Komponente anweisen, auf bestimmte Ereignisse einer anderen Komponente zu warten und diese dann erneut auszulösen, als ob sie von der ersten Komponente stammen. Die API-Dokumente enthalten das Beispiel eines Rasters, das das Speicherereignis weiterleitet load. Dies ist sehr praktisch, wenn Sie benutzerdefinierte Komponenten schreiben, die mehrere Unterkomponenten enthalten.

Der umgekehrte Vorgang, dh das Weiterleiten von Ereignissen, die von einer Kapselungskomponente empfangen wurden, mycmpan eine ihrer Unterkomponenten subcmp, kann auf diese Weise erfolgen

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