Объясните обработку событий ExtJS 4

130

Недавно я начал изучать ExtJS и не понимаю, как обрабатывать события. У меня нет опыта работы с предыдущими версиями ExtJS.

Прочитав различные руководства, руководства и страницы документации, я понял, как им пользоваться, но не понимаю, как это работает. Я нашел несколько руководств для более старых версий ExtJS, но не уверен, насколько они применимы в ExtJS 4.

Я специально ищу "последнее слово" в таких вещах, как

  • какие аргументы передаются функции обработки событий? Есть ли стандартный набор аргументов, которые всегда передаются?
  • как определить пользовательские события для пользовательских компонентов, которые мы пишем? как мы можем запустить это настраиваемое событие?
  • влияет ли возвращаемое значение (истина / ложь) на то, как всплывает событие? Если нет, как мы можем контролировать всплытие событий изнутри или вне обработчика событий?
  • есть ли стандартный способ регистрации слушателей событий? (До сих пор я встречал два разных способа, и я не уверен, почему использовался каждый метод).

Например, этот вопрос заставляет меня поверить, что обработчик событий может получать довольно много аргументов. Я видел другие руководства, где у обработчика всего два аргумента. Какие изменения?

jrharshath
источник
2
Только что заметил ... не по теме?
jrharshath 06
12
88 голосов за вопрос, 155 голосов за первый ответ, и великий и могущественный Эндрю решает, что этот вопрос не по теме. Происходит серьезная энергетическая поездка!
boatcoder
3
Я проголосовал за повторное открытие этого вопроса, поскольку ответы здесь - золотая жила. Я отредактировал вопрос, чтобы он лучше соответствовал стилю вопросов и ответов.
dbrin
1
Пожалуйста, откройте этот вопрос еще раз, потому что это действительно полезный и искренний вопрос. так слепо мы не можем закрыть это.
Пиюш Дхолария
2
Это хорошо сформулированный вопрос, и я не вижу причин его закрывать. Называть это не по теме - смешно. Проголосовали за повторное открытие.
Майк Фукс

Ответы:

222

Начнем с описания обработки событий элементов DOM.

Обработка событий узла DOM

Прежде всего, вы не захотите напрямую работать с узлом DOM. Вместо этого вы, вероятно, захотите использовать Ext.Elementинтерфейс. С целью назначения обработчиков событий Element.addListenerи Element.on(они эквивалентны) были созданы. Так, например, если у нас есть html:

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

и мы хотим добавить click обработчик событий.
Получим Element:

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

Теперь давайте проверим документы на предмет clickсобытия. Его обработчик может иметь три параметра:

щелкните (Ext.EventObject e, HTMLElement t, Object eOpts)

Зная все это, мы можем назначить обработчик:

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

Обработка событий виджетов

Обработка событий виджетов очень похожа на обработку событий узлов DOM.

Прежде всего, обработка событий виджетов осуществляется с помощью Ext.util.Observableмиксина. Чтобы правильно обрабатывать события, ваш виджет должен иметь Ext.util.Observableвид миксина. Все встроенные виджеты (например, панель, форма, дерево, сетка, ...) имеютExt.util.Observable по умолчанию используются в качестве миксина.

Для виджетов есть два способа назначения обработчиков. Первый - использовать по методу (или addListener). Например, создадим Buttonвиджет и назначим ему clickсобытие. Прежде всего, вы должны проверить документацию события на предмет аргументов обработчика:

нажмите (Ext.button. нажмите this, Event e, Object eOpts)

Теперь воспользуемся 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);
});

Второй способ - использовать конфигурацию слушателей виджета :

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

Обратите внимание, что Buttonвиджет - это особый вид виджетов. Событие клика можно назначить этому виджету с помощью handlerconfig:

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

Запуск пользовательских событий

Прежде всего, вам нужно зарегистрировать событие с помощью метода addEvents :

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

Используя addEvents метода необязательно. В комментариях к этому методу говорится, что использовать этот метод нет необходимости, но он предоставляет место для документации событий.

Чтобы запустить событие, используйте метод fireEvent :

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

arg1, arg2, arg3, /* ... */будет передан обработчику. Теперь мы можем обработать ваше событие:

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

Стоит отметить, что лучшее место для вставки вызова метода addEvents - это initComponentметод виджета, когда вы определяете новый виджет:

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

Предотвращение всплытия событий

Для предотвращения образования пузырей можно return falseили использовать Ext.EventObject.preventDefault(). Чтобы предотвратить действия браузера по умолчанию, используйтеExt.EventObject.stopPropagation() .

Например, назначим нашей кнопке обработчик события нажатия. И если не была нажата левая кнопка, предотвратить действие браузера по умолчанию:

myButton.on('click', function(btn, e){
  if (e.button !== 0)
    e.preventDefault();
});
Молекулярный человек
источник
3
это жадность, но есть ли способ сделать "addEvents" через какую-нибудь конфигурацию? :)
jrharshath 01
@jrharshath, насколько я знаю, к сожалению, нет способа сделать это через config.
Molecular Man
как создать эти -'myspecialevent1 ', я вижу, вы прикрепили его и обработали, но как мы их создаем?
heyNow
1
Блестящий ответ! Я новичок в ExtJs и искал способ ссылаться на любой элемент на странице и использовать на них обработчики событий, как jQuery. Ты меня этому научил! Спасибо!
Rutwick Gangurde
1
небольшая ошибка в разделе «Предотвращение всплытия событий». stopPropagation используется для предотвращения восходящей цепочки событий, а preventDefault используется для предотвращения поведения / действия по умолчанию.
MatRt
44

Акции по стрельбе

Как заставить контроллеры разговаривать друг с другом ...

В дополнение к очень отличному ответу выше я хочу упомянуть события в масштабе всего приложения, которые могут быть очень полезны в настройке MVC для обеспечения связи между контроллерами. (Extjs4.1)

Допустим, у нас есть контроллерная станция (примеры Sencha MVC) с полем выбора:

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

Когда поле выбора запускает событие изменения, функция onStationSelect запускается.

Внутри этой функции мы видим:

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

Это создает и запускает событие для всего приложения, которое мы можем прослушивать с любого другого контроллера.

Таким образом, в другом контроллере теперь мы можем узнать, когда было изменено поле выбора станции. Это делается путем прослушивания this.application.onследующего:

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

Если поле выбора было изменено, теперь мы также запускаем функцию onStationStartв контроллере Song...

Из документов Sencha:

События приложения чрезвычайно полезны для событий, которые имеют много контроллеров. Вместо того, чтобы прослушивать одно и то же событие представления в каждом из этих контроллеров, только один контроллер прослушивает событие представления и запускает событие уровня приложения, которое могут прослушивать другие. Это также позволяет контроллерам обмениваться данными друг с другом, не зная о существовании друг друга или не завися от него.

В моем случае: щелчок по узлу дерева для обновления данных на панели сетки.

Обновление 2016 благодаря @ gm2008 из комментариев ниже:

Что касается запуска пользовательских событий для всего приложения, теперь после публикации ExtJS V5.1 появился новый метод , который использует Ext.GlobalEvents.

Когда вы запускаете события, вы можете позвонить: Ext.GlobalEvents.fireEvent('custom_event');

Когда вы регистрируете обработчик события, вы вызываете: Ext.GlobalEvents.on('custom_event', function(arguments){/* handler codes*/}, scope);

Этот метод не ограничивается контроллерами. Любой компонент может обрабатывать настраиваемое событие, помещая объект компонента в качестве области входного параметра.

Найдено в Sencha Docs: MVC Part 2

mahatmanich
источник
1
Что касается запуска пользовательских событий для всего приложения, теперь после публикации ExtJS V5.1 появился новый метод, использующий Ext.GlobalEvents. Когда вы запускаете событие, вы вызываете. Ext.GlobalEvents.fireEvent('custom_event');Когда вы регистрируете обработчик события, вы вызываете Ext.GlobalEvents.on('custom_event', function(arguments){/* handler codes*/}, scope};Here is a fiddle . Этот метод не ограничивается контроллерами. Любой компонент может обрабатывать настраиваемое событие, помещая объект компонента в качестве входного параметра scope. Вопрос следует снова открыть.
GM2008
15

Еще одна хитрость для слушателей событий контроллера.

Вы можете использовать подстановочные знаки для отслеживания события из любого компонента:

this.control({
   '*':{ 
       myCustomEvent: this.doSomething
   }
});
dbrin
источник
12

Просто хотел добавить пару пенсов к превосходным ответам, приведенным выше: если вы работаете над Extjs 4.1 и у вас нет общих событий приложения, но они нужны, я использовал очень простой метод, который может помочь: простой объект, расширяющий Observable, и определите любые события приложения, которые могут вам понадобиться. Затем вы можете запускать эти события из любого места вашего приложения, включая фактический элемент html dom, и прослушивать их из любого компонента, передавая необходимые элементы из этого компонента.

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

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

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

Затем вы можете из любого другого компонента:

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

И запускайте их из любого компонента или элемента dom:

 MessageBus.fireEvent('event1', somearg);

 <input type="button onclick="MessageBus.fireEvent('event2', 'somearg')">
Harel
источник
Для информации, this.addEvents устарел, начиная с EXT JS 5.0. Так что сейчас нет необходимости добавлять события
Аджай Шарма
11

Еще две вещи, которые мне показалось полезным узнать, даже если они не являются частью вопроса.

Вы можете использовать этот relayEventsметод, чтобы сообщить компоненту, что он должен прослушивать определенные события другого компонента, а затем запускать их снова, как если бы они исходили от первого компонента. В документации по API приведен пример сетки, передающей loadсобытие магазина . Это очень удобно при написании пользовательских компонентов, которые инкапсулируют несколько подкомпонентов.

И наоборот, то есть передача событий, полученных инкапсулирующим компонентом, mycmpодному из его подкомпонентов subcmp, может быть выполнена следующим образом

mycmp.on('show' function (mycmp, eOpts)
{
   mycmp.subcmp.fireEvent('show', mycmp.subcmp, eOpts);
});
blahgonaut
источник