jQuery 使用 jQuery UI 部件工厂编写带状态的插件(翻译)
首先,我們要創(chuàng)建一個(gè)progress bar,它只允許我們簡單的設(shè)置進(jìn)度值。正如我們接下來將要看到的,我們需要通過調(diào)用 jQuery.widget 及其兩個(gè)參數(shù)來實(shí)現(xiàn)這一操作,這兩個(gè)參數(shù)分別是:將要創(chuàng)建的插件的名稱,以及一個(gè)包含該插件所支持方法的對象字面量(object literal)。
當(dāng)我們的插件被調(diào)用時(shí),它將創(chuàng)建一個(gè)新的插件實(shí)例,并且包含在該實(shí)例上下文(context)中的方法都會被執(zhí)行。這與標(biāo)準(zhǔn)的jQuery插件有兩個(gè)主要的區(qū)別。首先,上下文 (context)是一個(gè)對象,而不是DOM元素。其次,上下文(context)始終都是一個(gè)單獨(dú)的對象,而不是集合。
使用 jQuery UI 部件工廠創(chuàng)建一個(gè)簡單的,帶狀態(tài)的插件:
1 $.widget( "nmk.progressbar", { 2 3 _create: function() { 4 var progress = this.options.value + "%"; 5 this.element.addClass( "progressbar" ).text( progress ); 6 } 7 8 });?插件的名稱必須包含一個(gè)命名空間(namespace);在我們的例子當(dāng)中使用 nmk 作為命名空間(namespace)。關(guān)于命名空間(namespace)這里有一個(gè)限制,就是它只能夠擁有一個(gè)層級;換句話說,我們不能使用類似 nmk.foo 這樣的形式來作為命名空間(namespace)。同時(shí)我們看到部件工廠已經(jīng)為我們提供了兩個(gè)屬性。第一個(gè)屬性是 this.element ,它是一個(gè)只包含一個(gè)元素的jQuery對象。如果調(diào)用插件的jQuery對象包含多個(gè)元素,那么每一個(gè)元素將分別擁有一個(gè)插件實(shí)例,并且每一個(gè)插件實(shí)例都擁有自己的 this.element 屬性。第二個(gè)屬性是 this.options ,該屬性是一個(gè)散列,包含有與我們插件選項(xiàng)相對應(yīng)的所有鍵/值配對。
將選項(xiàng)傳遞給部件:
1 $( "<div />" ).appendTo( "body" ).progressbar({ value: 20 });當(dāng)我們調(diào)用 jQuery.widget 時(shí),它通過向 jQuery.fn 添加一個(gè)方法來擴(kuò)展jQuery(也是我們創(chuàng)建標(biāo)準(zhǔn)插件的方式)。被添加的方法的名稱基于你在調(diào)用 jQuery.widget 時(shí)所使用的名稱,不包含命名空間(namespace)。在我們的例子當(dāng)中,它將創(chuàng)建 jQuery.fn.progressbar。傳遞給插件的選項(xiàng)在插件實(shí)例內(nèi)部已經(jīng)在 this.options 中進(jìn)行了設(shè)置。
正如接下來我們將要展示的,我們可以為任何選項(xiàng)指定一個(gè)默認(rèn)值。當(dāng)設(shè)計(jì)API時(shí),你應(yīng)當(dāng)想好該插件最常見的使用情形,以便可以設(shè)置合適的默認(rèn)值,并使所有的選項(xiàng)都是完全可選的。
為部件設(shè)置默認(rèn)選項(xiàng)值:
1 $.widget( "nmk.progressbar", { 2 3 // Default options. 4 options: { 5 value: 0 6 }, 7 8 _create: function() { 9 var progress = this.options.value + "%"; 10 this.element.addClass( "progressbar" ).text( progress ); 11 } 12 13 });為部件添加方法
現(xiàn)在我們可以初始化progress bar了,通過調(diào)用插件實(shí)例中的方法我們使其能夠執(zhí)行一些操作。要在插件中定義方法,我們只需要在傳遞給 jQuery.widget 的對象字面量(object literal)當(dāng)中包含該方法。同時(shí)我們可以在方法名前面添加下劃線(_)來使其成為私有方法。
創(chuàng)建部件方法:
1 $.widget( "nmk.progressbar", { 2 options: { 3 value: 0 4 }, 5 6 _create: function() { 7 var progress = this.options.value + "%"; 8 this.element.addClass("progressbar").text( progress ); 9 }, 10 11 // Create a public method. 12 value: function( value ) { 13 14 // No value passed, act as a getter. 15 if ( value === undefined ) { 16 17 return this.options.value; 18 19 // Value passed, act as a setter. 20 } else { 21 22 this.options.value = this._constrain( value ); 23 var progress = this.options.value + "%"; 24 this.element.text( progress ); 25 26 } 27 28 }, 29 30 // Create a private method. 31 _constrain: function( value ) { 32 33 if ( value > 100 ) { 34 value = 100; 35 } 36 37 if ( value < 0 ) { 38 value = 0; 39 } 40 41 return value; 42 } 43 44 });?要在插件實(shí)例上調(diào)用方法,只需要將方法的名稱傳遞給jQuery插件。如果所調(diào)用的是帶參數(shù)的方法,只需將這些參數(shù)放置在方法名的后面。
在插件實(shí)例上調(diào)用方法:
1 var bar = $( "<div />" ).appendTo( "body").progressbar({ value: 20 }); 2 3 // Get the current value. 4 alert( bar.progressbar( "value" ) ); 5 6 // Update the value. 7 bar.progressbar( "value", 50 ); 8 9 // Get the current value again. 10 alert( bar.progressbar( "value" ) );操縱部件的選項(xiàng)
option方法是插件中內(nèi)置的方法之一。該方法允許你在初始化之后對屬性進(jìn)行設(shè)置。該方法的工作方式與jQuery的 .css() 和 .attr() 方法相同:你可以通過向其傳遞名稱來將它作為getter,傳遞名稱和值來將它作為setter,傳遞一個(gè)鍵/值配對的散列來同時(shí)設(shè)置多個(gè)值。當(dāng)它被作為getter時(shí),插件將返回與傳遞進(jìn)來的名稱相對應(yīng)的選項(xiàng)的當(dāng)前值。當(dāng)它被作為setter時(shí),每一個(gè)已經(jīng)設(shè)置的選項(xiàng)都會調(diào)用插件的 _setOption 方法。當(dāng)選項(xiàng)發(fā)生改變時(shí),我們可以在插件中指定 _setOption 方法來進(jìn)行反應(yīng)。
當(dāng)選項(xiàng)被設(shè)置時(shí)作出響應(yīng):
1 $.widget( "nmk.progressbar", { 2 3 options: { 4 value: 0 5 }, 6 7 _create: function() { 8 this.element.addClass( "progressbar" ); 9 this._update(); 10 }, 11 12 _setOption: function( key, value ) { 13 this.options[ key ] = value; 14 this._update(); 15 }, 16 17 _update: function() { 18 var progress = this.options.value + "%"; 19 this.element.text( progress ); 20 } 21 22 });添加回調(diào)函數(shù)
添加回調(diào)函數(shù)讓用戶可以在插件狀態(tài)發(fā)生變化時(shí)作出反應(yīng)是擴(kuò)展插件的一種簡單的方式。下面我們將看到如何為progress bar添加回調(diào)函數(shù),來表明進(jìn)度何時(shí)到達(dá)百分之百。 _trigger 方法帶有三個(gè)參數(shù):回調(diào)函數(shù)的名稱,原生事件對象用于觸發(fā)回調(diào)函數(shù),以及與事件有關(guān)的數(shù)據(jù)的散列。回調(diào)函數(shù)的名稱是唯一必要的參數(shù),而其他的參數(shù)在用戶希望在插件上實(shí)現(xiàn)自己的方法時(shí)將十分有用。例如,我們編寫了一個(gè)可拖動的插件,當(dāng)觸發(fā)拖動回調(diào)函數(shù)時(shí),我們可以傳遞一個(gè)原生的鼠標(biāo)移動事件,用戶將可以通過這一事件對象,在 x/y 坐標(biāo)的基礎(chǔ)上對拖動作出反應(yīng)。
為用戶擴(kuò)展提供回調(diào)函數(shù):
1 $.widget( "nmk.progressbar", { 2 3 options: { 4 value: 0 5 }, 6 7 _create: function() { 8 this.element.addClass( "progressbar" ); 9 this._update(); 10 }, 11 12 _setOption: function( key, value ) { 13 this.options[ key ] = value; 14 this._update(); 15 }, 16 17 _update: function() { 18 var progress = this.options.value + "%"; 19 this.element.text( progress ); 20 if ( this.options.value == 100 ) { 21 this._trigger( "complete", null, { value: 100 } ); 22 } 23 } 24 25 });回調(diào)函數(shù)其實(shí)就是額外的選項(xiàng),因此你可以像對待其它選項(xiàng)那樣對其進(jìn)行設(shè)置。每當(dāng)回調(diào)函數(shù)被執(zhí)行時(shí),一個(gè)與之對應(yīng)的事件也會被觸發(fā)。事件的名稱由插件的名稱及回調(diào)函數(shù)的名稱連接而成。回調(diào)函數(shù)和事件同時(shí)接收兩個(gè)相同的參數(shù):事件對象和與時(shí)間有關(guān)的數(shù)據(jù)的散列,我們將在之后看到相關(guān)的演示。
如果你希望插件的某項(xiàng)功能可以被用戶阻止,最好的做法就是創(chuàng)建一個(gè)可取消的回調(diào)函數(shù)。用戶可以像取消原生事件那樣來取消回調(diào)函數(shù),或者與之相關(guān)的事件:通過調(diào)用 event.preventDefault() 或者使用 return false 。如果用戶取消了回調(diào)函數(shù), _trigger 方法將返回 false 使得你可以在插件中實(shí)現(xiàn)合適的功能。
綁定部件事件:
1 var bar = $( "<div />" ).appendTo( "body" ).progressbar({ 2 3 complete: function( event, data ) { 4 alert( "Callbacks are great!" ); 5 } 6 7 }).bind( "progressbarcomplete", function( event, data ) { 8 9 alert( "Events bubble and support many handlers for extreme flexibility." ); 10 11 alert( "The progress bar value is " + data.value ); 12 13 }); 14 15 bar.progressbar( "option", "value", 100 );部件工廠:深入(Under the Hood)
當(dāng)你調(diào)用 jQuery.widget 時(shí),它會為你的插件創(chuàng)建一個(gè)構(gòu)造函數(shù)(constructor),并將你傳遞進(jìn)來的對象字面量(object literal)作為對象實(shí)例的原型(prototype)。所有自動添加到插件中的功能都來自于一個(gè)基本的部件原型(widget prototype),它被定義為 jQuery.Widget.prototype。當(dāng)插件實(shí)例被創(chuàng)建之后,它通過 jQuery.data 將插件存儲在原始的DOM元素當(dāng)中,并使用插件的名稱來作為鍵值。
由于插件實(shí)例直接與DOM元素產(chǎn)生聯(lián)系,因此如果你愿意的話,可以直接訪問插件實(shí)例而非通過插件所暴露的方法。這將允許你直接調(diào)用插件實(shí)例上的方法,而非通過將方法的名稱作為字符串傳遞給插件,此外你還將可以直接訪問插件的屬性。
1 var bar = $( "<div />") 2 .appendTo( "body" ) 3 .progressbar() 4 .data( "progressbar" ); 5 6 // Call a method directly on the plugin instance. 7 bar.option( "value", 50 ); 8 9 // Access properties on the plugin instance. 10 alert( bar.options.value );插件的構(gòu)造函數(shù)(constructor)和原型(prototype)所擁有的巨大好處之一就是使插件更易擴(kuò)展。通過在插件原型(prototype)上添加或修改方法,我們可以改變插件所有實(shí)例的行為。例如,如果我們想要在progress bar中添加一個(gè)方法,用于重置進(jìn)度為零。我們可以在插件的原型上添加這一方法,并且它立刻就可以被任意插件的實(shí)例所調(diào)用。
1 $.nmk.progressbar.prototype.reset = function() { 2 this._setOption( "value", 0 ); 3 };清理
在某些情況下,允許用戶隨時(shí)應(yīng)用和取消應(yīng)用插件將十分有用。你可以通過使用 destroy 方法來達(dá)成這一目的。在 destroy 方法當(dāng)中,你應(yīng)當(dāng)撤銷插件在初始化時(shí)或之后的使用中所進(jìn)行的一切動作。 destroy 方法將在被插件所關(guān)聯(lián)的元素從DOM當(dāng)中被移除時(shí),自動被調(diào)用,因此這同樣可以用來進(jìn)行垃圾回收。默認(rèn)情況下, destroy 方法會移除DOM元素和插件實(shí)例間的聯(lián)系, 因此在插件的 destroy 方法中調(diào)用基類的方法十分的重要。
為部件添加 destroy 方法:
1 $.widget( "nmk.progressbar", { 2 3 options: { 4 value: 0 5 }, 6 7 _create: function() { 8 this.element.addClass("progressbar"); 9 this._update(); 10 }, 11 12 _setOption: function( key, value ) { 13 this.options[ key ] = value; 14 this._update(); 15 }, 16 17 _update: function() { 18 var progress = this.options.value + "%"; 19 this.element.text( progress ); 20 if ( this.options.value === 100 ) { 21 this._trigger( "complete", null, { value: 100 } ); 22 } 23 }, 24 25 destroy: function() { 26 this.element 27 .removeClass( "progressbar" ) 28 .text( "" ); 29 30 // Call the base destroy function. 31 $.Widget.prototype.destroy.call( this ); 32 } 33 34 });總結(jié)
部件工廠是創(chuàng)建帶狀態(tài)插件的唯一方法。有少數(shù)一些不同的模型可以被使用,并且它們各有千秋。部件工廠為你解決了大部分常見的問題并且極大的提升了工作效率,它同時(shí)提升了代碼的復(fù)用率,使其和其它帶狀態(tài)的插件一樣的更加適用于jQuery UI。
?
原文地址:http://learn.jquery.com/plugins/stateful-plugins-with-widget-factory/
轉(zhuǎn)載于:https://www.cnblogs.com/joysoy/p/3537786.html
總結(jié)
以上是生活随笔為你收集整理的jQuery 使用 jQuery UI 部件工厂编写带状态的插件(翻译)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [转载] 30分钟泛型教程
- 下一篇: 百度地图API使用之实现定位