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?
javascript
extjs
event-handling
extjs4
jrharshath
źródło
źródło
Odpowiedzi:
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.Element
interfejsu. W celu przypisania obsługi zdarzeńElement.addListener
iElement.on
(są one równoważne) zostały utworzone. Na przykład, jeśli mamy html:<div id="test_node"></div>
i chcemy dodać
click
obsługę zdarzeń.Pobierzmy
Element
:var el = Ext.get('test_node');
Teraz sprawdźmy w dokumentach
click
wydarzenie. Jego program obsługi może mieć trzy parametry: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.Observable
mixin. Aby poprawnie obsługiwać zdarzenia, twój widget musi zawierać sięExt.util.Observable
jako mixin. Wszystkie wbudowane widżety (takie jak Panel, Form, Drzewo, Siatka, ...) mająExt.util.Observable
domyś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órzmyButton
widget i przypiszmyclick
do niego zdarzenie. Przede wszystkim powinieneś sprawdzić dokumentację zdarzenia pod kątem argumentów handlera: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
Button
widget to specjalny rodzaj 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); } });
Odpalanie zdarzeń niestandardowych
Przede wszystkim musisz zarejestrować zdarzenie metodą addEvents :
myButton.addEvents('myspecialevent1', 'myspecialevent2', 'myspecialevent3', /* ... */);
Korzystanie z tej
addEvents
metody 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
initComponent
podczas 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 false
lub użyćExt.EventObject.preventDefault()
. Aby zapobiec używaniu domyślnej akcji przeglądarkiExt.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(); });
źródło
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
onStationSelect
jest 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.on
nastę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ę
onStationStart
w kontrolerzeSong
ró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
źródło
Ext.GlobalEvents.fireEvent('custom_event');
Kiedy rejestrujesz program obsługi zdarzenia, wywołujeszExt.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ściowyscope
. Pytanie powinno zostać ponownie otwarte.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 } });
źródło
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')">
źródło
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
relayEvents
metody, 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ącejload
zdarzenie 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
mycmp
do jednego z jego podkomponentówsubcmp
, można zrobić w ten sposóbmycmp.on('show' function (mycmp, eOpts) { mycmp.subcmp.fireEvent('show', mycmp.subcmp, eOpts); });
źródło