web-dev-qa-db-ja.com

ExtJS 4イベント処理の説明

私は最近ExtJSの学習を始めましたが、イベントの処理方法を理解するのに苦労しています。 ExtJSの以前のバージョンの経験はありません。

さまざまなマニュアル、ガイド、およびドキュメントのページを読んで、その使用方法を理解しましたが、どのように機能するのか明確ではありません。古いバージョンのExtJS向けのチュートリアルをいくつか見つけましたが、ExtJS 4でそれらがどのように適用できるかわかりません。

特に次のような「最終単語」を探しています。

  • イベント処理関数はどの引数を渡しますか?常に渡される引数の標準セットはありますか?
  • 作成するカスタムコンポーネントのカスタムイベントを定義する方法これらのカスタムイベントをどのように起動できますか?
  • 戻り値(true/false)はイベントのバブルに影響しますか?そうでない場合、イベントハンドラーの内部または外部からイベントバブリングをどのように制御できますか?
  • イベントリスナーを登録する標準的な方法はありますか? (今までに2つの異なる方法に出くわしましたが、それぞれの方法が使用された理由はわかりません)。

たとえば、 この質問 は、イベントハンドラーが非常に多くの引数を受け取ることができると信じさせます。ハンドラへの引数が2つしかない他のチュートリアルを見てきました。何が変わりますか?

127
jrharshath

DOM要素のイベント処理を説明することから始めましょう。

DOMノードイベント処理

まず、DOMノードを直接操作したくないでしょう。代わりに、おそらく Ext.Element インターフェイスを利用したいと思うでしょう。イベントハンドラーを割り当てるために、 Element.addListener および Element.on (これらは同等)が作成されました。したがって、たとえば、htmlがある場合:

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

clickイベントハンドラーを追加します。
Elementを取得しましょう:

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

では、 click イベントのドキュメントを確認しましょう。ハンドラーには3つのパラメーターがあります。

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をミックスインとして含める必要があります。すべての組み込みウィジェット(パネル、フォーム、ツリー、グリッドなど)には、デフォルトでミックスインとしてExt.util.Observableがあります。

ウィジェットには、ハンドラーを割り当てる2つの方法があります。最初の1つは、 on メソッド(またはaddListener)を使用することです。たとえば、Buttonウィジェットを作成して、clickイベントを割り当てましょう。まず、イベントのドキュメントでハンドラーの引数を確認する必要があります。

click(Ext.button.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);
});

2番目の方法は、ウィジェットの 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();
});
219
Molecular Man

アプリケーション全体のイベントの起動

コントローラーが互いに対話する方法...

上記の非常に優れた答えに加えて、コントローラー間の通信を可能にする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も起動します...

Sencha docsから:

アプリケーションイベントは、多くのコントローラーを持つイベントに非常に役立ちます。これらの各コントローラーで同じビューイベントをリッスンする代わりに、1つのコントローラーのみがビューイベントをリッスンし、他のコントローラーがリッスンできるアプリケーション全体のイベントを起動します。これにより、コントローラーは互いの存在を知らずに、または依存せずに互いに通信できます。

私の場合:ツリーノードをクリックして、グリッドパネルのデータを更新します。

以下のコメントから@ gm2008のおかげで2016を更新します:

アプリケーション全体のカスタムイベントの発生に関しては、ExtJS V5.1が公開された後、Ext.GlobalEventsを使用する新しいメソッドがあります。 。

イベントを発生させるとき、次を呼び出すことができます:Ext.GlobalEvents.fireEvent('custom_event');

イベントのハンドラーを登録するとき、次を呼び出します:Ext.GlobalEvents.on('custom_event', function(arguments){/* handler codes*/}, scope);

この方法はコントローラーに限定されません。任意のコンポーネントは、コンポーネントオブジェクトを入力パラメータースコープとして配置することにより、カスタムイベントを処理できます。

Sencha Docs:MVCパート2にあります

43
mahatmanich

コントローラーイベントリスナーのもう1つのトリック。

ワイルドカードを使用して、任意のコンポーネントからのイベントを監視できます。

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

上記の優れた回答にペンスを2つ追加したかっただけです。Extjs4.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')">
12
Harel

質問の一部でなくても、知っておくと便利なことがもう2つあります。

relayEventsメソッドを使用すると、別のコンポーネントの特定のイベントをリッスンするようにコンポーネントに指示し、最初のコンポーネントから発生したかのようにそれらを再度発生させることができます。 APIドキュメントは、ストアloadイベントを中継するグリッドの例を提供します。いくつかのサブコンポーネントをカプセル化するカスタムコンポーネントを作成するときに非常に便利です。

別の方法、つまり、カプセル化コンポーネントmycmpが受信したイベントをそのサブコンポーネントsubcmpの1つに渡す方法は、次のように実行できます。

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