Wyjaśnij obsługę zdarzeń ExtJS 4

130

Niedawno zacząłem uczyć się ExtJS i mam problem ze zrozumieniem, jak obsługiwać zdarzenia. Nie mam doświadczenia z żadnymi wcześniejszymi wersjami ExtJS.

Czytając różne podręczniki, przewodniki i strony dokumentacji, dowiedziałem się, jak go używać, ale nie wiem, jak to działa. Znalazłem kilka samouczków dla starszych wersji ExtJS, ale nie jestem pewien, jak mają one zastosowanie w ExtJS 4.

W szczególności patrzę na „ostatnie słowo” w takich sprawach

  • jakie argumenty są przekazywane funkcji obsługującej zdarzenia? Czy istnieje standardowy zestaw argumentów, które zawsze są przekazywane?
  • jak zdefiniować zdarzenia niestandardowe dla komponentów, które piszemy? jak możemy uruchomić te niestandardowe zdarzenie?
  • czy zwracana wartość (prawda / fałsz) wpływa na sposób, w jaki zdarzenie bąbelkuje? Jeśli nie, w jaki sposób możemy kontrolować propagację zdarzeń z poziomu programu obsługi zdarzeń lub poza nim?
  • czy istnieje standardowy sposób rejestrowania detektorów zdarzeń? (Do tej pory natknąłem się na dwa różne sposoby i nie jestem pewien, dlaczego użyto każdej metody).

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

jrharshath
źródło
2
Właśnie zauważyłem ... poza tematem?
jrharshath
12
88 głosów za pytaniem, 155 głosów za pierwszą odpowiedzią, a wielki i potężny Andrzej decyduje, że to jest poza tematem. Trwa poważna podróż mocy!
boatcoder
3
Głosowałem za ponownym otwarciem tego pytania, ponieważ odpowiedzi tutaj są żyłą złota. Zredagowałem pytanie, aby lepiej pasowało do stylu Q i A.
dbrin
1
Otwórz to pytanie ponownie, ponieważ jest to naprawdę pomocne i prawdziwe pytanie. tak ślepo nie możemy go zamknąć.
Piyush Dholariya
2
To dobrze sformułowane pytanie i nie widzę powodu, aby je zamykać. Odwołanie tego poza temat jest śmieszne. Zagłosowano na ponowne otwarcie.
Mike Fuchs

Odpowiedzi:

222

Zacznijmy od opisu obsługi zdarzeń w elementach 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ś użyć Ext.Elementinterfejsu. W celu przypisania obsługi zdarzeń Element.addListeneri Element.on(są one równoważne) zostały utworzone. Na przykład, jeśli mamy html:

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

i chcemy dodać clickobsługę zdarzeń.
Pobierzmy Element:

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

Teraz sprawdźmy w dokumentach clickwydarzenie. Jego program obsługi może mieć trzy parametry:

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

Znając to wszystko możemy przypisać handlerowi:

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

Obsługa zdarzeń widżetów

Obsługa zdarzeń widżetów jest bardzo podobna do obsługi zdarzeń w węzłach DOM.

Po pierwsze, obsługa zdarzeń widżetów jest realizowana poprzez wykorzystanie Ext.util.Observablemixin. Aby poprawnie obsługiwać zdarzenia, twój widget musi zawierać się Ext.util.Observablejako mixin. Wszystkie wbudowane widżety (takie jak Panel, Form, Drzewo, Siatka, ...) mają Ext.util.Observabledomyślnie domieszkę.

W przypadku widżetów istnieją dwa sposoby przypisywania programów obsługi. Pierwszy - to użycie na metodzie (lub addListener). Na przykład stwórzmy Buttonwidget i przypiszmy clickdo niego zdarzenie. Przede wszystkim powinieneś sprawdzić dokumentację zdarzenia pod kątem argumentów handlera:

kliknij (Przycisk Ext. przycisk this, Event e, Object 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 konfiguracji słuchaczy widżetu :

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 Buttonwidget to specjalny rodzaj widżetów. Zdarzenie Click można przypisać do tego widżetu za pomocą handlerconfig:

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

Odpalanie zdarzeń niestandardowych

Przede wszystkim musisz zarejestrować zdarzenie metodą addEvents :

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

Korzystanie z tej addEventsmetody jest opcjonalne. Komentarze do tej metody mówią, że nie ma potrzeby korzystania z tej metody, ale zapewnia miejsce na dokumentację wydarzeń.

Aby uruchomić zdarzenie, użyj metody fireEvent :

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

arg1, arg2, arg3, /* ... */zostaną przekazane do programu obsługi. 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 wstawienia wywołania metody addEvents jest metoda widżetu initComponentpodczas definiowania nowego widżetu:

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 bulgotaniu wydarzeń

Aby zapobiec bulgotaniu, możesz return falselub użyć Ext.EventObject.preventDefault(). Aby zapobiec używaniu domyślnej akcji przeglądarki Ext.EventObject.stopPropagation().

Na przykład przypiszmy obsługę zdarzenia kliknięcia do naszego przycisku. A jeśli nie został kliknięty lewy przycisk, zablokuj domyślną akcję przeglądarki:

myButton.on('click', function(btn, e){
  if (e.button !== 0)
    e.preventDefault();
});
Molecular Man
źródło
3
to jest chciwość, ale czy jest jakiś sposób na zrobienie rzeczy "addEvents" poprzez jakąś konfigurację? :)
jrharshath
@jrharshath, o ile wiem, niestety nie ma możliwości zrobienia tego przez config.
Molecular Man
jak można stworzyć te -'myspecialevent1 ', widzę, że załączyłeś to i poradziłeś sobie z tym, ale jak je tworzymy?
hejNow
1
Świetna odpowiedź! Jestem nowy w ExtJs i szukałem sposobu na odwołanie się do dowolnego elementu na stronie i użycie na nich obsługi zdarzeń, tak jak w jQuery. Ty mnie tego nauczyłeś! Dzięki!
Rutwick Gangurde,
1
mały błąd w sekcji „Zapobieganie propagowaniu wydarzeń”. stopPropagation służy do zapobiegania bublingowi zdarzeń, a disableDefault do zapobiegania domyślnemu zachowaniu / działaniu.
MatRt
44

Wypalanie wydarzeń w szerokim zakresie

Jak sprawić, by kontrolery rozmawiały ze sobą ...

Oprócz bardzo świetnej odpowiedzi powyżej, chcę wspomnieć o zdarzeniach obejmujących całą aplikację, 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 wyboru wyzwala zdarzenie zmiany, funkcja onStationSelectjest uruchamiana.

W ramach tej funkcji widzimy:

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

Tworzy to i uruchamia zdarzenie obejmujące całą aplikację, którego możemy słuchać z dowolnego innego kontrolera.

W ten sposób w innym kontrolerze możemy teraz wiedzieć, kiedy pole wyboru stacji zostało zmienione. Odbywa się to poprzez słuchanie this.application.onnastępujących poleceń:

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, teraz odpalamy funkcję onStationStartw kontrolerze Songrównież ...

Z dokumentacji Sencha:

Zdarzenia aplikacji są niezwykle przydatne w przypadku zdarzeń, które mają wiele kontrolerów. Zamiast nasłuchiwać tego samego zdarzenia widoku w każdym z tych kontrolerów, tylko jeden kontroler nasłuchuje zdarzenia widoku i uruchamia zdarzenie dotyczące całej aplikacji, którego mogą nasłuchiwać pozostałe. Pozwala to również kontrolerom na komunikowanie się ze sobą bez wiedzy o istnieniu innych lub polegania na nich.

W moim przypadku: Kliknięcie węzła drzewa, aby zaktualizować dane w panelu siatki.

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

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

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

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

Ta metoda nie ogranicza się do kontrolerów. Każdy składnik może obsłużyć zdarzenie niestandardowe, umieszczając obiekt składnika jako zakres parametru wejściowego.

Znalezione w Sencha Docs: MVC Part 2

Mahatmanich
źródło
1
Jeśli chodzi o uruchamianie niestandardowych zdarzeń w całej aplikacji, po opublikowaniu ExtJS V5.1 pojawiła się nowa metoda, która korzysta z Ext.GlobalEvents. Kiedy odpalasz zdarzenie, wywołujesz Ext.GlobalEvents.fireEvent('custom_event');Kiedy rejestrujesz program obsługi zdarzenia, wywołujesz Ext.GlobalEvents.on('custom_event', function(arguments){/* handler codes*/}, scope};Here is a fiddle . Ta metoda nie ogranicza się do kontrolerów. Każdy składnik może obsłużyć zdarzenie niestandardowe, umieszczając obiekt składnika jako parametr wejściowy scope. Pytanie powinno zostać ponownie otwarte.
gm2008
15

Jeszcze jedna sztuczka dla słuchaczy zdarzeń kontrolera.

Możesz używać symboli wieloznacznych, aby obserwować wydarzenie z dowolnego komponentu:

this.control({
   '*':{ 
       myCustomEvent: this.doSomething
   }
});
dbrin
źródło
12

Chciałem tylko dodać kilka pensów do doskonałych odpowiedzi powyżej: Jeśli pracujesz nad pre Extjs 4.1 i nie masz wydarzeń dla całej aplikacji, ale ich potrzebujesz, używam bardzo prostej techniki, która może pomóc: Utwórz prosty obiekt rozszerzający Observable i zdefiniuj dowolne zdarzenia dotyczące całej aplikacji, których możesz potrzebować. Następnie możesz uruchamiać te zdarzenia z dowolnego miejsca w aplikacji, w tym z rzeczywistego elementu html dom, i słuchać ich z dowolnego składnika, przekazując wymagane elementy z tego składnika.

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

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

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

Następnie możesz z dowolnego innego komponentu:

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

I odpal je z dowolnego komponentu lub elementu dom:

 MessageBus.fireEvent('event1', somearg);

 <input type="button onclick="MessageBus.fireEvent('event2', 'somearg')">
Harel
źródło
Dla informacji, this.addEvents zostało wycofane, począwszy od EXT JS 5.0. Nie ma więc potrzeby teraz dodawać wydarzeń
Ajay Sharma
11

Jeszcze tylko dwie rzeczy, które uznałem za pomocne, nawet jeśli tak naprawdę nie są częścią pytania.

Możesz użyć tej relayEventsmetody, aby nakazać komponentowi nasłuchiwanie pewnych zdarzeń innego komponentu, a następnie uruchomić je ponownie, tak jakby pochodziły z pierwszego komponentu. Dokumentacja API podaje przykład siatki przekazującej loadzdarzenie sklepu . Jest to bardzo przydatne podczas pisania niestandardowych komponentów, które obejmują kilka podkomponentów.

Na odwrót, tj. Przekazywanie zdarzeń odebranych przez komponent enkapsulujący mycmpdo jednego z jego podkomponentów subcmp, można zrobić w ten sposób

mycmp.on('show' function (mycmp, eOpts)
{
   mycmp.subcmp.fireEvent('show', mycmp.subcmp, eOpts);
});
blahgonaut
źródło