jQuery UI 擴充小工具
jQuery UI 的部件庫(Widget Factory)使得創建小部件變得更加容易,這些小部件擴展了已有小部件的功能。這樣子您就能在現有的基礎上創建出功能強大的小部件,也可以在已有的小部件功能上做細微的調整。
注意:在學習本章節之前,需要明白什麼是零件庫(Widget Factory),以及它是怎麼運作的。如果您對這些知識還不熟悉,那麼請先查看如何使用部件庫(Widget Factory)章節。
建立小部件擴充
透過元件庫(Widget Factory)建立小工具是透過向$.widget()
傳遞小元件名稱和一個原型物件來完成的。下面的實例是在 "custom" 命名空間中建立一個 "superDialog" 小工具。
$.widget( "custom.superDialog", {} );
為了支援擴展,$.widget()
可選性地接受作為父部件使用的小部件的建構子。當指定一個父部件時,把它當作第二個參數傳遞,放在小部件名稱後面,在小部件原型物件前面。
就像上面的實例,下面也要在 "custom" 命名空間中建立一個 "superDialog" 小工具。但這次傳遞的是jQuery UI 的dialog(對話框)小部件的建構子($.ui.dialog
),表示superDialog 小工具應該使用jQuery UI 的dialog(對話框)小工具作為父部件。
$.widget( "custom.superDialog", $.ui.dialog, {} );
在這裡,superDialog 和 dialog 兩個小工具實質上是等價的,只是名稱和命名空間不同而已。為了讓我們新的小部件更具特點,我們可以添加一些方法到它的原型物件上。
小部件的原型物件是傳遞給 $.widget()
的最後一個參數。到目前為止,我們的實例使用的是一個空的物件。現在讓我們為這個物件添加一個方法:
$.widget( "custom.superDialog", $.ui.dialog, { red: function() { this.element.css( "color", "red" ); } }); // Create a new <div>, convert it into a superDialog, and call the red() method. $( "<div>I am red</div>" ) .superDialog() .superDialog( "red" );
現在 superDialog
有一個 red()
方法,這會把它的文字顏色改為紅色。請注意,部件庫(Widget Factory)是如何自動設定 this
為小部件的實例物件。如需了解實例上所有可用的方法和屬性列表,請存取 部件庫(Widget Factory) API 文件。
擴充已有的方法
有時候,您需要調整或加入已有部件方法的行為。您可以把方法名稱指定為原型物件上需要重載的方法名稱。下面的實例重載了 dialog(對話框)的 open()
方法。由於對話方塊預設是開啟的,當運行這段程式碼時,"open"
將會被記錄。
$.widget( "custom.superDialog", $.ui.dialog, { open: function() { console.log( "open" ); } }); // Create a new <div>, and convert it into a superDialog. $( "<div>" ).superDialog();
當執行這段程式碼時,有一個問題。由於我們重載了 open()
的預設行為,所以 dialog(對話框)不再顯示在螢幕上。
當我們在原型物件上使用方法,我們實際上是重載了原始的方法,在原型鏈中使用了一個新的方法。
為了讓父元件方法可用,元件庫(Widget Factory)提供了兩個方法 - _super()
和 _superApply()
。
使用_super()
和_superApply()
來存取父元件
_super()
和_superApply ()
在父部件中呼叫了同樣的方法。請看下面的實例。就像上一個實例,這個實例也重載了 open()
方法來記錄 "open"
。然而,這次運行 _super()
是呼叫了 dialog(對話方塊)的 open()
,並且開啟對話方塊。
$.widget( "custom.superDialog", $.ui.dialog, { open: function() { console.log( "open" ); // Invoke the parent widget's open(). return this._super(); } }); $( "<div>" ).superDialog();
_super()
和_superApply()
其實等同於原先的Function.prototype.call()
和Function .prototype.apply()
方法。因此,_super()
接受一個參數列表,_superApply()
接受一個陣列作為參數。下面的實例示範了這二者之間的差異。
$.widget( "custom.superDialog", $.ui.dialog, { _setOption: function( key, value ) { // Both invoke dialog's setOption() method. _super() requires the arguments // be passed as an argument list, _superApply() as a single array. this._super( key, value ); this._superApply( arguments ); } });
重新定義小部件
jQuery UI 1.9 新增了重新定義小部件的功能。因此,可以不用建立一個新的小部件,我們只需要傳遞 $.widget()
這樣一個已有的小部件名稱和建構函式。下面的實例在 open()
中新增了相同的記錄,但不是透過建立一個新的小部件來完成的。
$.widget( "ui.dialog", $.ui.dialog, { open: function() { console.log( "open" ); return this._super(); } }); $( "<div>" ).dialog();
透過這個方法,我們可以擴展一個已有的小部件方法,但是仍然可以使用_super()
來存取原始的方法- 這些都不是透過創建一個新的小部件來完成的,而是直接重定義小部件即可。
小部件(Widgets)和多態性(Polymorphism)
當在小部件擴展及它們的插件之間進行交互時候,有一點值得注意,父部件的插件不能用來呼叫子部件元素上的方法。下面的實例演示了這一點。
$.widget( "custom.superDialog", $.ui.dialog, {} ); var dialog = $( "<div>" ).superDialog(); // This works. dialog.superDialog( "close" ); // This doesn't. dialog.dialog( "close" );
上面的實例中,父部件的插件,dialog()
,不能呼叫 superDialog 元素上的 close()
方法。如需了解更多呼叫小工具方法的知識,請查看 小工具(Widget)方法呼叫。
自訂個人化實例
目前為止,我們看到的實例都有在小部件原型上擴展的方法。在原型上重載的方法影響了小部件的所有實例。
為了示範這一點,請看下面的實例。 dialog(對話方塊)的兩個勢力都使用了相同的 open()
方法。
$.widget( "ui.dialog", $.ui.dialog, { open: function() { console.log( "open" ); return this._super(); } }); // Create two dialogs, both use the same open(), therefore "open" is logged twice. $( "<div>" ).dialog(); $( "<div>" ).dialog();
有時候,您只需要改變小部件的某個實例的行為。為了做到這一點,您需要使用正常的 JavaScript 屬性分配,以獲得對實例的引用,並重載該方法。具體如下面實例所示。
var dialogInstance = $( "<div>" ) .dialog() // Retrieve the dialog's instance and store it. .data( "ui-dialog" ); // Override the close() method for this dialog dialogInstance.close = function() { console.log( "close" ); }; // Create a second dialog $( "<div>" ).dialog(); // Select both dialogs and call close() on each of them. // "close" will only be logged once. $( ":data(ui-dialog)" ).dialog( "close" );
個人化實例的重載方法技術是完美的一次性自訂。