Поясніть обробку подій 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.