Latest web development tutorials

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" );

個性化實例的重載方法技術是完美的一次性定制。