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

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

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

Я специально смотрю на "последнее слово" на вещи как

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

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

5 ответов


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

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

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

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

и мы хотим добавить click обработчик событий.
Давайте восстановим Element:

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

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

нажать( доб.EventObject e, HTMLElement t, Object eOpts)

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

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

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

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

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

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

нажать( доб.кнопка.Кнопка this, событие e, объект 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);
});

второй способ-использовать виджет слушатель 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);
    }
  }
});

обратите внимание, что Button виджет-это особый вид Виджеты. Событие Click может быть назначено этому виджету с помощью 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);
  }
});

пользовательские события стрельбы

прежде всего вам нужно зарегистрировать событие с помощью 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().

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

myButton.on('click', function(btn, e){
  if (e.button !== 0)
    e.preventDefault();
});

стрельба применение широкие события

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

в дополнение к очень большому ответу выше, я хочу упомянуть широкие события приложения, которые могут быть очень полезны в настройке 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?');
    },
}

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

из документов Сенча:

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

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

обновление 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


еще один трюк для прослушивателей событий контроллера.

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

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

просто хотел добавить пару пенсов к отличным ответам выше: Если вы работаете над pre Extjs 4.1 и не имеете событий, но нуждаетесь в них, я использую очень простую технику, которая может помочь: Создайте простой объект, расширяющий наблюдаемый, и определите любые события приложения, которые могут вам понадобиться. Затем вы можете запускать эти события из любого места приложения, включая фактический элемент 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')">

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

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

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

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