Объясните обработку событий ExtJS 4 - PullRequest
126 голосов
/ 31 августа 2011

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

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

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

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

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

Ответы [ 5 ]

218 голосов
/ 31 августа 2011

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

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

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

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

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

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

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

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 mixin.Для правильной обработки событий ваш виджет должен связываться с Ext.util.Observable как миксин.Все встроенные виджеты (такие как Panel, Form, Tree, Grid, ...) по умолчанию имеют Ext.util.Observable как миксин.

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

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

Второй способ - использовать listeners 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 - это особый вид виджетов.Событие клика может быть назначено этому виджету с помощью 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().

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

myButton.on('click', function(btn, e){
  if (e.button !== 0)
    e.preventDefault();
});
42 голосов
/ 16 августа 2012

События запуска приложения в целом

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

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

Допустим, у нас есть контроллер Station (примеры 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: MVC Part 2

13 голосов
/ 04 декабря 2012

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

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

this.control({
   '*':{ 
       myCustomEvent: this.doSomething
   }
});
12 голосов
/ 02 мая 2013

Просто хотел добавить пару пенсов к превосходным ответам выше: если вы работаете над пред 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')">
11 голосов
/ 12 декабря 2012

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

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

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

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