javascript
JavaScript之三:jQuery插件开发(一)
在早期的開發中,正如前面閉包中所提到的那樣,人們一開始并沒有意識到要開發出插件這么個玩意兒,都是遇到啥寫啥。在長期的工作中,人們發現很多代碼是重復的,寫了一遍又一遍,以登錄頁面為例,每寫一次都需要重新校驗username、password、email、tel等等內容,這些工作毫無意義只是簡單地重復,而且大多數都是大同小異,人們開始不耐煩了,并且著手去找到一種辦法,希望能夠從這些簡單無意義的重復勞動中解放出來。既然寫這些代碼不可避免,那么能否減少寫這些代碼的次數呢?更進一步的思考,能不能有這么一種方式,當我需要這段代碼的時候,我就可以直接拿來用,哪怕只是做一點點更改也行。這樣插件就應運而生了。它封裝了某個功能,實現了代碼的可重用性,在實際工作中可以拿來反復的使用。
一個最最簡單的jquery插件只有一個函數來實現一個功能就夠了,它僅僅只需要用來被重復調用。比如我的工作中要實現這么一個功能:當我點擊時,改變div框中的背景顏色。這個功能在頁面中需要反復被使用到,那么我就迫切地需要開發一個插件來實現它。下面是不使用任何插件的情況下,每一次頁面的使用都需要重新寫。
<!DOCTYPE html> <html><head><meta charset="utf-8"/><script src="jquery-1.11.3.js"></script><style>div{width:200px;height:200px;border:1px solid #000;}</style></head><script>$(function(){$("input").click(function(){$("div").css("background","#ccc"); })});</script><body><input type="button" value="動我一下試試"><br><br><div></div></body> </html>這里將給出全部代碼,下文中為避免啰嗦將只給出關鍵代碼。當開發插件時它的插件的代碼如下:
1 jQuery.fn.extend({ 2 test : function(){ 3 $(this).css("background","#ccc"); 4 } 5 })//插件名為下文的plugins.js它的調用代碼
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"/> 5 <script src="jquery-1.11.3.js"></script>//引入jquery 6 <script src="plugins.js"></script>//引入jquery插件 7 <style> 8 div{ 9 width:200px; 10 height:200px; 11 border:1px solid #000; 12 } 13 </style> 14 </head> 15 <script> 16 $(function(){ 17 $("input").click(function(){ 18 $("div").test(); //調用插件中的test()方法 19 }) 20 }); 21 </script> 22 <body> 23 <input type="button" value="動我一下試試"><br><br> 24 <div></div> 25 </body> 26 </html>在上面的插件代碼中,我們發現test()方法是嵌套在jQuery.fn.extend()中,那么這個jQuery.fn.extend()到底是什么呢?事實上,絕多大數插件都是基于它開發的,它就是大名鼎鼎的jquery對象方法插件機制,與之齊名的還有jQuery.extend(),也就是jquery全局函數插件機制。他們都被用來創建插件,在繼續下文之前,很有必要來了解下二者的區別。
一、jQuery.extend()
事實上,當jQuery.extend()用來做插件開發的時候,在其參考文檔中表述的是用來在jQuery命名空間上增加新函數。此處的jQuery可以理解為一個function類,對它進行extend擴展實際上就相當于給他添加一個靜態方法,這個方法是擴展在jQuery類上面的,它的調用是不需要new出一個實例,而是直接采用“jQuery+方法”的形式調用,與jQuery的實例沒有任何關系。借用參考文檔的例子:
jQuery代碼:
1 jQuery.extend({ 2 min: function(a, b) { return a < b ? a : b; }, 3 max: function(a, b) { return a > b ? a : b; } 4 });運行結果:
1 jQuery.min(2,3); // => 2 2 jQuery.max(4,5); // => 5二、jQuery.fn.extend()
在jQuery.fn.extend()中,從底層代碼知道fn代表的是prototype,它實際上是擴展jQuery對象也就是原型prototype上的方法,既然是擴展在jQuery對象上的方法,那么就是說要jQuery對象才能調用嘍。而什么是jQuery對象呢?不就是jQuery的實例嗎?換個方式來說,$(selector)不就是jQuery對象嗎?這正如前面的例子所述,調用的時候是$("div").test(),而$("div")是jQuery對象。
jQuery代碼:
1 jQuery.fn.extend({ 2 test : function(){ 3 $(this).css("background","#ccc"); 4 } 5 })調用代碼:
$(function(){$("input").click(function(){$("div").test(); //調用插件中的test()方法 ,用的是$("div")而非$ })});通過區別比較上面2種開發插件的方式,可以看到基于對象方法機制插件使用會廣泛得多,現實中大部分都是基于對象方法開發的插件。
然而在上述例子中,那個簡單的插件很快就遇到了新的問題。隨著頁面的復雜性增加,在代碼中會引入多個庫或框架,$這么火熱,大家都想套套近乎沾沾光,于是大家的命名都采取了$,一個不小心,$的指代就會被第三方庫或框架給覆蓋了,它指代的就不再是jquery而是第三方庫了。這就是jquery多庫共存問題。
對于jquery多庫共存問題,參考文檔給出了解決方案,有時候,你不得不為一些精妙絕倫的解決方案而拍案叫絕。
一、jQuery.noConflict()
運行這個函數將變量$的控制權讓渡給第一個實現它的那個庫。這有助于確保jQuery不會與其他庫的$對象發生沖突。在運行這個函數后,就只能使用jQuery變量訪問jQuery對象。例如,在要用到$("div p")的地方,就必須換成jQuery("div p")。代碼如下:
1 jQuery.noConflict(); 2 // 使用 jQuery 3 jQuery("div p").hide();//此處不再使用$而是使用jQuery 4 // 使用其他庫的 $() 5 $("content").style.display = 'none';二、創建一個新的別名用以在接下來的庫中使用jQuery對象:
1 var j = jQuery.noConflict(); 2 // 基于 jQuery 的代碼 3 j("div p").hide(); 4 // 基于其他庫的 $() 代碼 5 $("content").style.display = 'none';三、創建一個匿名函數(function($){})(jQuery):
1 jQuery.noConflict(); 2 (function($) { 3 $(function() { 4 // 使用 $ 作為 jQuery 別名的代碼 5 }); 6 })(jQuery); 7 // 其他用 $ 作為別名的庫的代碼這是一個匿名函數,這個函數可以理解為這樣:
1 var f= function ($){ 2 $(function(){ 3 4 }); 5 } 6 f(jQuery);對于函數f,$作為形參,是局部變量,可以在函數內部自由滴使用$,當他被調用時,jQuery作為實參被傳遞進去。這樣做的好處就是,函數f里定義的函數和變量僅僅在函數f里有效,$并不會與外面的$相沖突。調用執行時,jQuery會取代形參$,這樣既實現了讓$指代了jQuery,又避免了$之間的互相沖突,這也是使用的最多的方案。
上面的插件就該是:
1 (function($){ 2 $.fn.extend({ 3 test : function(){ 4 $(this).css("background","#ccc"); 5 } 6 }) 7 })(jQuery)這樣就創建了一個方便使用的對象方法插件,同時解決了多庫共存的問題。
然而現實問題并沒有這么簡單,雖然完成了插件的基本功能,但是還不夠,用戶在長期的使用過程中,覺得不夠智能,他想自定義div框的顏色,而不僅僅是灰色;同時他還想能夠改變框的大小。好吧,問題又來了,但是沒關系,程序員天生就是來解決問題的。
怎么辦?首先想到的就是傳遞參數進來,給test()增加參數,這個參數可以讓用戶自定義,用戶想怎樣就怎樣,這個好解決。我們來看下面代碼:
1 (function($){ 2 $.fn.extend({ 3 test : function(opts){ 4 $(this).css(opts); 5 } 6 }) 7 })(jQuery)在調用時代碼如下:
$("div").test({width:"500px",background:"red"})這樣來看問題得到解決,但,這還不夠完美。假如說test有許多參數怎么辦?用戶只想定義其中一部分參數,其他的保持不變怎么辦?用戶怎么知道允許自定義哪些參數?最好的解決方式無疑是:指明哪些參數用戶可以去自定義,當用戶需要定義某些參數時,盡管自定義好了,其他的參數不變,使用插件的默認值。
這里就有如下的解決辦法:
var opts=$.extend(defaluts,opts)$.extend() 除了可以用來創建插件之外,還可以進行對象合并,這里只講此處需要用到的用法,更多用法參照http://api.jquery.com/jQuery.extend/,或者可以看我稍后的中文翻譯http://www.cnblogs.com/liudaxia/p/4910106.html。舉例來說明:
1 var Amy={2 age:20, 3 sex:gril, 4 }5 var Dale={6 age:20, 7 sex:boy 8 weight:120 9 } 10 $.extend(Amy,Dale)//此時的Amy={age:20,sex:boy,weight:120}可以看到,Amy的屬性被修改,它繼承了Dale的weight屬性,同時sex屬性被覆蓋。這對于我們要實現的功能有什么用呢?假如說,我們把默認值放在Amy的位置,把傳進來的參數opts放在Dale的位置,會有什么樣的效果呢?顯而易見,新傳進來的自定義參數屬性將會被保留,而默認值的相同的屬性則會用戶自定義的給覆蓋,這樣就巧妙的實現了我們想要的效果。用上面的實例來說明,看插件代碼:
jQuery.fn.extend({test : function(opts){var defaults={// 默認值設置,此處與html代碼中的div的style設置保持一致。width:"200px",background:"#fff",height:"200px"}var s=$.extend(defaults,opts);// s為合并之后的屬性,它是{width:"500px",background:"red",height:"200px"}$(this).css(s); } })調用代碼:
$("div").test({width:"500px",background:"red"})最終得到的效果就是寬500高200的紅色矩形。原來默認的高200屬性得到保留,用戶想要的改變寬和顏色的目的也達到。用戶在調用的時候,想自定義哪個參數,就把哪個參數傳進去,同時沒被定義的屬性將會被保留。
還可以對其進行優化,比如假如獲取的div框不止一個,那么這個時候就需要使用each()進行遍歷。甚至可以把用戶不自定義參數的情況考慮進去,這些都比較簡單,就不具體介紹了。那么最終的插件如下:
1 (function($){2 $.fn.extend({//下面的opts就是用戶自定義的參數3 test : function(opts){//定義test()方法,這就是我們的插件。可以改寫成$.fn.test=function(opts){}4 var defaults={// 默認值設置,此處與html代碼中的div的style設置保持一致。5 width:"200px",6 background:"#fff",7 height:"200px"8 } 9 opts=opts||{};//opts可能為空,也就是用戶沒有自定義,此時使用默認值 10 var s=$.extend(defaults,opts);// s為合并之后的屬性,它是{width:"500px",background:"red",height:"200px"} 11 this.each(function(){//遍歷 12 $(this).css(s); //功能實現代碼,也就是改變div框的寬和背景顏色 13 }); 14 } 15 }) 16 })(jQuery)以上就是一個簡單的插件的開發過程。本人也是初學,歡迎指出錯誤共同探討交流共同進步,謝謝。
轉載于:https://www.cnblogs.com/liudaxia/p/4905993.html
《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀總結
以上是生活随笔為你收集整理的JavaScript之三:jQuery插件开发(一)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: FreeRTOS初步认识
- 下一篇: 回文链表