Поясніть обробку подій ExtJS 4


130

Нещодавно я почав вивчати ExtJS, і у мене виникли труднощі з розумінням поводження з подіями. Я не маю досвіду жодної попередньої версії ExtJS.

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

Я спеціально дивлюсь на "заключне слово" на такі речі

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

Наприклад, це запитання змушує мене вважати, що обробник подій може отримати досить багато аргументів. Я бачив інші навчальні посібники, де є лише два аргументи для обробника. Що змінюється?


2
Щойно помітили ... поза темою?
— jrharshath

12
88 Оновлення запитання, 155 відгуків на першу відповідь, і великий і могутній Андрій вирішує, що це поза темою. Триває серйозна поїздка на владу!
— boatcoder

3
Я проголосував за повторне відкриття цього питання, оскільки відповіді тут - це золота шахта. Я відредагував питання, щоб краще відповідати стилю Q та A.
— дбрин

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

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

натисніть (Ext.button. Запустіть це, 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

@jrharshath, наскільки я знаю, на жаль, немає можливості зробити це через config.
— Молекулярна людина

як один створює ці -'myspecialevent1 ', я бачу, ви це додали та обробляли, але як ми їх створимо?
— heyNow

1
Блискуча відповідь! Я новачок у ExtJs і шукав спосіб посилатися на будь-який елемент сторінки та використовувати обробники подій на них, як і jQuery. Ти мене навчив! Дякую!
— Рутвік Ґангурде

1
невелика помилка в розділі "Запобігання бурхливості подій". stopPropagation використовується для запобігання розгортання події, а prevenDefault використовується для запобігання поведінки / дії за замовчуванням.
— MatRt

44

Стріляння подій із широкими додатками

Як змусити контролерів розмовляти між собою ...

На додаток до дуже чудової відповіді вище, я хочу зазначити події, що широко застосовуються до додатків, які можуть бути дуже корисними в установці MVC, щоб забезпечити зв'язок між контролерами. (extjs4.1)

Скажімо, у нас є контролер Station (приклади MVC Sencha) з полем вибору:

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...

З Документів Сенчі:

Події програми надзвичайно корисні для подій, у яких є багато контролерів. Замість того, щоб слухати одну і ту ж подію перегляду у кожному з цих контролерів, лише один контролер прослуховує подію перегляду та запускає подію, пов’язану з усім додатком, яку можуть слухати інші. Це також дозволяє контролерам спілкуватися один з одним, не знаючи про існування один одного або залежно від цього.

У моєму випадку: Клацнувши на дереві, щоб оновити дані на панелі сітки.

Оновлення 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


1
Що стосується запуску користувальницьких подій на весь додаток, тепер після публікації ExtJS V5.1 з'явився новий метод, який використовує Ext.GlobalEvents. Коли ви запускаєте подію, ви телефонуєте. Ext.GlobalEvents.fireEvent('custom_event');Коли ви реєструєте обробника події, ви телефонуєте Ext.GlobalEvents.on('custom_event', function(arguments){/* handler codes*/}, scope};Ось загадка . Цей метод не обмежується контролерами. Будь-який компонент може обробляти власну подію, розміщуючи об'єкт компонента як вхідний параметр scope. Питання слід знову відкрити.
— gm2008

15

Ще одна хитрість для слухачів подій контролера.

Ви можете використовувати символи символів для спостереження за подією з будь-якого компонента:

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

12

Просто хотілося додати пару пенсів до чудових відповідей вище: Якщо ви працюєте над попередньою версією 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')">

Щойно для інформації, цей файл.addEvents був застарілий, починаючи з EXT JS 5.0. Тож немає потреби додавати події зараз
— Аджай Шарма

11

Ще дві речі, які мені здаються корисними, навіть якщо вони не є частиною питання.

Ви можете скористатися relayEventsметодом, щоб сказати компоненту прослуховувати певні події іншого компонента, а потім знову запустити їх так, ніби вони походять з першого компонента. Документи API наводять приклад сітки, що передає магазинload подію . Це досить зручно при написанні користувацьких компонентів, які інкапсулюють кілька підкомпонентів.

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

mycmp.on('show' function (mycmp, eOpts)
{
   mycmp.subcmp.fireEvent('show', mycmp.subcmp, eOpts);
});
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.