2009年11月16日

ExtJS 筆記 - EXTJS 的事件處理函式

jQuery 不同,ExtJS 的事件處理函式略顯複雜了些!原因在於 jQuery 的事件綁定機制永遠只作用於 jQuery 物件,但 ExtJS 的事件綁定機制卻必須先確定事件綁定對象的種類。

在 ExtJS 中有兩種類型的 Ext 物件可以進行事件綁定,一種是 Ext.Component,另一種是 Ext.Element。雖然它們都會對應到頁面上的 HTML Element ,但實際上來看 Ext.Component 算是以 Ext.Element 為基礎進行擴充的衍生物件,常因為特別需要而自行提供許多自定的事件,例如 Ext.form.Checkbox 這個 Ext.Component 物件會額外提供 check 事件,當然你可以把這個 check 事件當成原本 click 事件的再包裝。

所以說只要弄清楚事件綁定的對象後也就能夠確定所使用的事件處理函式的參數型態,對 Ext.Element 而言它的事件處理函式參數格式為:
/* 此的處 element 是一個 HTML Element ,也就是原本的 HTML DOM 物件 */
function eventHandler( event, element, object ) { }
但若是 Ext.Component 的話它的事件處理函式則為:
function eventHandler( component [, value/state ] ) { }
其實寫 ExtJS 應用系統很容易遇到事件處理函式未能如預期反應的情況,這是因為搞錯了事件作用的對象以及事件處理函式的參數匹配不正確所導致,要不是因為此次的系統開發時用到了 Ext.form.Checkbox 這個元素,也許格揆我還沒發現原來 ExtJS 的事件模型有分成兩種情形,而大致搜尋了一下也沒有啥文章特別提到這個明明就在 API 文件中,但工程師顯然不會特別注意到的情形。

但我們該怎麼取得 Ext.ComponentExt.Element 物件呢?只要記住除了 Ext.getCmp() 外,其他的 DomQuery 函式都只會傳回 Ext.ElementExt.CompositeElement(可把它當成多個 Ext.Element 物件的集合) 物件。

以下的範例可看出 Ext.ComponentExt.Element/Ext.CompositeElement 在注冊事件處理函式時的差異:
<html>
    <head>
        <link rel="stylesheet" type="text/css" href="http://www.extjs.com/deploy/dev/resources/css/ext-all.css" />
        <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
        <script type="text/javascript" src="http://www.extjs.com/deploy/dev/adapter/jquery/ext-jquery-adapter.js"></script>
        <script type="text/javascript" src="http://www.extjs.com/deploy/dev/ext-all.js"></script>
        <script text="text/javascript">
            function init() {
                var viewport = new Ext.Viewport({
                    layout: 'form'
                    ,defaults: {
                        xtype: 'checkbox'
                        ,labelWidth: 70
                        ,labelAlign: 'right'
                    }
                    ,items: [
                        {
                            fieldLabel: '選項一'
                            ,id: 'chbox1'
                        }
                        ,{
                            fieldLabel: '選項二'
                            ,id: 'chbox2'
                        }
                        ,{
                            fieldLabel: '按鈕一'
                            ,id: 'btn1'
                            ,xtype: 'button'
                            ,text: '按鈕一'
                        }
                    ]
                });
  
                // 對 Ext.Component:chbox1 物件注冊 check 事件處理函式
                Ext.getCmp( 'chbox1' ).on( 'check', function ( chbox, checked ) {
                    alert( chbox.getId() + ' is ' + checked );
                });
  
                // 對所有的 Ext.CompositeElement:Checkbox 物件注冊 click 事件處理函式
                // 實際上有兩個物件被注冊了事件處理函式
                // 如果想在 Ext.Element 物件上綁定 check 事件的話,它是不會生效也不會有錯誤的喔!
                Ext.select( 'input[type=checkbox]' ).on( 'click', function( evt, el ) {
                    Ext.Msg.alert( 'Event Tester', el.id + ' is ' + el.checked );
                });

                // 對 Ext.Component:btn1 物件注冊 click 事件處理函式  
                Ext.getCmp( 'btn1' ).on( 'click', function( button ) {
                    alert( button.getId() + ' clicked' );
                });
  
                // 對所有的 Ext.CompositeElement:button 物件注冊 click 事件處理函式
                // 實際上有一個物件被注冊了事件處理函式
                Ext.select( 'button' ).on( 'click', function( evt, el ) {
                    Ext.Msg.alert( 'Event Tester', el.id );
                });
 
                return viewport;
            }
     
            $( document ).ready( init );
        </script>
    </head>
    <body>
    
    </body>
</html>

參考資訊: