Wyjaśnij obsługę zdarzeń ExtJS 4

Ostatnio zacząłem uczyć się ExtJS i mam problemy ze zrozumieniem, jak obsługiwać wydarzenia. Nie mam doświadczenia z poprzednimi wersjami ExtJS.

Czytając różne podręczniki, przewodniki i strony dokumentacji, odkryłem, jak z niego korzystać, ale nie jestem pewien, jak to działa. Znalazłem kilka samouczków dla starszych wersji ExtJS, ale nie jestem pewien, jak mają zastosowanie w ExtJS 4.

Szukam konkretnie "ostatniego słowa" o rzeczach jak

  • jakie argumenty przekazuje funkcja obsługi zdarzeń? Czy istnieje standardowy zestaw args, który zawsze przechodzi?
  • Jak zdefiniować niestandardowe zdarzenia dla niestandardowych komponentów, które piszemy? jak możemy odpalić te niestandardowe wydarzenie?
  • czy wartość zwracana (true / false) ma wpływ na pęcherzyki zdarzeń? Jeśli nie, w jaki sposób możemy kontrolować bulgoczenie zdarzeń z wewnątrz lub poza obsługą zdarzeń?
  • czy istnieje standardowy sposób rejestracji słuchaczy zdarzeń? (Natknąłem się na dwa różne sposoby do tej pory, i nie jestem pewien, dlaczego każda metoda została użyta).

Na przykład, to pytanie prowadzi mnie do przekonania, że obsługa zdarzeń może otrzymać sporo argumentów. Widziałem inne tutoriale, w których są tylko dwa argumenty do prowadzącego. Jakie zmiany?

Author: Community, 2011-08-31

5 answers

Zacznijmy od opisu obsługi zdarzeń elementów DOM.

Obsługa zdarzeń węzła DOM

Przede wszystkim nie chciałbyś pracować bezpośrednio z węzłem DOM. Zamiast tego prawdopodobnie chciałbyś wykorzystać Ext.Element interfejs. Do celów przypisania programów obsługi zdarzeń, Element.addListener oraz Element.on (są równoważne) zostały stworzone. Tak więc, na przykład, jeśli mamy html:

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

I chcemy dodać click obsługę zdarzenia.
Odzyskajmy Element:

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

Teraz sprawdźmy dokumenty dla click wydarzenie. Może mieć trzy parametry:

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

Znając to wszystko możemy przypisać obsługę:

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

Obsługa widgetów

Obsługa zdarzeń widgetów jest bardzo podobna do obsługi zdarzeń węzłów DOM.

Przede wszystkim obsługa zdarzeń widgetów jest realizowana poprzez wykorzystanie Ext.util.Observable mixin. Aby poprawnie obsłużyć zdarzenia, widget musi zawierać Ext.util.Observable jako mixin. Wszystkie wbudowane widżety (takie jak Panel, formularz, drzewo, Siatka,...) domyślnie posiada Ext.util.Observable jako mixin.

Dla widżetów są dwa sposoby przypisywania programów obsługi. Pierwszym - jest użycie na metodzie (lub addListener). Stwórzmy na przykład widżet Button i przypiszmy do niego Zdarzenie click. Po pierwsze należy sprawdzić dokumenty zdarzenia pod kątem argumentów Handlera:

Click (Ext.guzik.Button this, Event e, Obiekt eOpts)

Teraz użyjmy 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);
});

Drugim sposobem jest użycie widgetu słuchaczy 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);
    }
  }
});

Zauważ, że Button widget jest specjalnym rodzajem widżetów. Zdarzenie Click można przypisać do tego widżetu za pomocą 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);
  }
});

Niestandardowe odpalanie zdarzeń

Najpierw musisz zarejestrować wydarzenie używając metody addEvents :

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

Użycie metody addEvents jest opcjonalne. Jako komentarze do tej metody powiedzmy, że nie ma potrzeby stosowania tej metody, ale zapewnia ona miejsce na dokumentację zdarzeń.

Aby odpalić Zdarzenie użyj metody fireEvent :

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

arg1, arg2, arg3, /* ... */ / align = "left" / Teraz możemy obsłużyć Twoje wydarzenie:

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

Warto wspomnieć, że najlepszym miejscem do wstawiania addevents wywołania metody jest metoda initComponent widgetu podczas definiowania nowego widgetu:

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

Zapobieganie bąbelkom zdarzeń

Aby zapobiec bubbling można return false lub użyć Ext.EventObject.preventDefault(). Aby zapobiec domyślnemu działaniu przeglądarki, użyj Ext.EventObject.stopPropagation().

Na przykład przypisajmy obsługę zdarzenia click do naszego przycisku. A jeśli nie kliknięto lewego przycisku, zapobiegaj domyślnej akcji przeglądarki:

myButton.on('click', function(btn, e){
  if (e.button !== 0)
    e.preventDefault();
});
 216
Author: Molecular Man,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-29 06:26:30

Strzelanie aplikacji wide events

Jak sprawić, by kontrolerzy ze sobą rozmawiali ...

Oprócz bardzo świetnej odpowiedzi powyżej chcę wspomnieć o zdarzeniach aplikacji, które mogą być bardzo przydatne w konfiguracji MVC, aby umożliwić komunikację między kontrolerami. (extjs4. 1)

Powiedzmy, że mamy stację kontrolera (przykłady Sencha MVC) z polem wyboru:

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

Gdy pole select uruchamia Zdarzenie change, Funkcja onStationSelect jest zwolniony.

W obrębie tej funkcji widzimy:

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

To tworzy i wywołuje zdarzenie całej aplikacji, które możemy odsłuchać z dowolnego innego kontrolera.

Tak więc w innym kontrolerze możemy teraz wiedzieć, kiedy pole wyboru stacji zostało zmienione. Można to zrobić poprzez słuchanie this.application.on w następujący sposób:

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

Jeśli pole wyboru zostało zmienione, uruchamiamy teraz funkcję onStationStart również w kontrolerze Song...

Od Sencha docs:

zdarzenia aplikacji są niezwykle przydatne dla zdarzeń, które mają wiele kontrolerów. Zamiast nasłuchiwać tego samego zdarzenia view w każdym z tych kontrolerów, tylko jeden kontroler nasłuchuje zdarzenia view i wywołuje zdarzenie dla całej aplikacji, którego inne mogą nasłuchać. Pozwala to również kontrolerom komunikować się ze sobą bez wiedzy o istnieniu innych lub w zależności od ich istnienia.

W moim przypadku: kliknięcie na węzeł drzewa w celu aktualizacji danych w Panel siatki.

Aktualizacja 2016 dzięki @ gm2008 z komentarzy poniżej:

Jeśli chodzi o uruchamianie niestandardowych zdarzeń w całej aplikacji, po opublikowaniu ExtJS V5.1 jest nowa metoda, która używa Ext.GlobalEvents.

Kiedy odpalasz zdarzenia, możesz zadzwonić: Ext.GlobalEvents.fireEvent('custom_event');

Kiedy rejestrujesz obsługę zdarzenia, dzwonisz: Ext.GlobalEvents.on('custom_event', function(arguments){/* handler codes*/}, scope);

Ta metoda nie jest ograniczona do kontrolerów. Każdy komponent może obsłużyć niestandardowe zdarzenie poprzez umieszczenie obiekt komponentu jako zakres parametru wejściowego.

Znaleziono w Sencha Docs: MVC Part 2

 42
Author: mahatmanich,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-21 11:05:46

Jeszcze jedna sztuczka dla Controller event listeners.

Możesz używać symboli wieloznacznych do oglądania zdarzenia z dowolnego komponentu:

this.control({
   '*':{ 
       myCustomEvent: this.doSomething
   }
});
 13
Author: dbrin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-12-04 19:31:59

Chciałem tylko dodać kilka groszy do doskonałych odpowiedzi powyżej: Jeśli pracujesz na Pre Extjs 4.1 i nie masz zdarzeń w całej aplikacji, ale ich potrzebujesz, używam bardzo prostej techniki, która może pomóc: Utwórz prosty obiekt rozszerzający obserwowalny i zdefiniuj w nim dowolne zdarzenia o zasięgu aplikacji. Następnie można uruchomić te zdarzenia z dowolnego miejsca w aplikacji, w tym rzeczywisty element HTML dom i słuchać ich z dowolnego komponentu, przekazując wymagane elementy z tego komponent.

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

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

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

Wtedy można, z dowolnego innego składnika:

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

I odpalić je z dowolnego elementu lub elementu dom:

 MessageBus.fireEvent('event1', somearg);

 <input type="button onclick="MessageBus.fireEvent('event2', 'somearg')">
 12
Author: Harel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-02 19:44:02

Jeszcze tylko dwie rzeczy, które pomogły mi wiedzieć, nawet jeśli nie są częścią pytania, naprawdę.

Możesz użyć metody relayEvents, aby powiedzieć komponentowi, aby nasłuchał pewnych zdarzeń innego komponentu, a następnie odpalił je ponownie, tak jakby pochodzą z pierwszego komponentu. Dokumentacja API zawiera przykład siatki przekazującej Zdarzenie store load. Jest to bardzo przydatne przy pisaniu niestandardowych komponentów, które zawierają kilka podskładników.

Odwrotnie, tzn. przechodząc dalej zdarzenia odbierane przez komponent enkapsulujący mycmp do jednego z jego podskładników subcmp, można wykonać w ten sposób

mycmp.on('show' function (mycmp, eOpts)
{
   mycmp.subcmp.fireEvent('show', mycmp.subcmp, eOpts);
});
 11
Author: blahgonaut,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-12-12 09:21:11