摘要:所以要先了解一下插件的三種開發(fā)方式通過來擴展通過向添加新的方法通過應用的部件工廠方式創(chuàng)建第三種方法是用來開發(fā)更高級的部件的。
jQuery插件開發(fā)模式
說到jQuery插件的編寫,起初我把它當做封裝一個方法那樣簡單,這顯然是錯的,因為這讓我一開始完全不知道如何下手去編寫一個插件。所以要先了解一下jQuery插件的三種開發(fā)方式:
通過$.extend()來擴展jQuery
通過$.fn 向jQuery添加新的方法
通過$.widget()應用jQuery UI的部件工廠方式創(chuàng)建
第三種方法是用來開發(fā)更高級的jQuery部件的。
第一種方法過于簡單,僅僅是在jQuery命名空間或者可以理解為在jQuery身上添加了一個靜態(tài)方法而已,調用時直接通過$.myfunction()調用,而不需要選中DOM元素,這種方法比較適用于定義一些輔助方法,比如定義一個console來輸出特定格式的信息,然后再任何需要的地方調用這個方法。比如下面的例子:
$.extend({ printTime: function(){ var now = new Date(), y = now.getFullYear(), m = now.getMonth()+1, d = now.getDate(); console.log(y +"-"+ m +"-"+ d); } }); /*調用*/ $.printTime();
輸出結果:
在這里要說一下關于$.extend(),jQuery的擴展方法
extend擴展方法的原型:
extend(dest,src1,src2,src3,...);
它的含義是將src1,src2,src3,...合并到dest中,返回值為合并后的dest,由此可見通過合并后,dest的結構會被修改了,如果不希望被修改,則可以如下使用:
var defaults = {name1:"content1",name2:"content2"} var options = {name1:"Jone"} var settings = $.extend({},defaults,options); /*結果*/ //settings = {name1:"Jone",name2:"content2"}
這個方法一般用來在編寫插件是用自定義插件參數去覆蓋插件的默認參數
省略dest參數$.extend(src)
該方法就是將src合并到jQuery的全局對象中,如下例子,就是將hello方法合并到jQuery的全局對象中
$.extend({ hello:function(){ alert("hello!"); } });
如上面所說的,通過$.extend()來擴展jQuery這種開發(fā)模式只能為jQuery類添加簡單的靜態(tài)方法,無法操作DOM元素,所以我們通常使用第二種開發(fā)模式進行簡單的插件編寫。
通過$.fn 向jQuery添加新的方法(插件開發(fā))基本方法$.fn.extend(obj) (為什么這里是$.fn.extend()而不是$.fn呢) 首先先來看看$.fn是什么意思
jQuery.fn = jQuery.prototype = { init:function(selector,context){...}; };
可以發(fā)現(xiàn),原來$.fn = $.prototype,那么$.fn.extend(obj)就是對$.prototype進行擴展,就是為jQuery類添加一個“成員函數”,jQuery類的實例可以使用這個“成員函數”。$.extend()的調用并不會把方法擴展到對象的實例上,或者說根本不需要實例化一個jQuery對象來調用$.extend()的方法;而$.fn.extend()的調用把方法擴展到了對象的prototype上,所以實例化一個jQuery對象時,它就具有了這些方法,這是很重要的。這就是插件機制了
$.fn.extend(myplugin) 等價于 $.prototype.extend(myplugin) 等價于$.fn.myplugin
編寫一個簡單的插件就是往$.fn添加一個方法(myplugin),然后插件代碼在里面展開,然后通過$(selector).myplugin()調用該插件里面的方法,如下面的例子
/*改變標簽文本的顏色,其他不受影響*/
這是p標簽,文本的顏色由黑色變?yōu)樗{色
這是div標簽,文本的顏色沒有變化
結果如下
這里要特別注意的是this,在這里指的是調用該插件的元素,但是在別的地方又指代不同時又需要用jQuery重新包裝才能調用,需要理解清楚。
鏈式調用
在插件代碼里是處理每個具體的元素而不是對一個集合進行處理,由上面已經知道this指代jQuery選擇器返回的集合,那么通過調用jQuery的.each()方法就可以處理集合中的每個元素了,需要注意的是,此時在each方法內部,this指代普通的DOM元素,需要用$(this)來調用jQuery方法
jQuery有一個優(yōu)雅的特性就是支持鏈式調用,而為了是編寫的插件也支持鏈式調用,只需return this.each(...);把jQuery對象返回出來,就可以繼續(xù)調用其他插件來處理這個jQuery對象。
這是p標簽1,我的編號是
這是p標簽2,我的編號是
這是p標簽3,我的編號是
結果:
讓插件接收參數
到此已經可以編寫一個簡單的插件了,但是一個強大的插件應該是可以讓使用者隨意定制的,所以需要提供合適的參數,如果使用者沒有提供參數,則使用插件默認的參數。在處理插件參數的接收上,用到了前面說到的$.extend()方法。使用如下:
結果如下,編號從5開始,默認是1開始
面向對象的插件開發(fā)
支持鏈式調用,支持自定義參數,就可以寫出一個健壯靈活的插件了,但是如果要編寫一個代碼量大的復雜插件,如何組織代碼就成了一個需要面臨的問題,可能會需要一個方法的時候就去定義一個function,當需要另一個方法時再隨便在代碼中一個地方定義一個function,同時也留下了毫無規(guī)則的散落在代碼各處的變量,這樣的結果是代碼不方便維護,也不夠清晰,甚至會出現(xiàn)變量污染的結果。
//定義MyPlugin對象 var MyPlugin = function(ele,opt){ //設置參數 //定義變量 //定義私有方法 } //定義MyPlugin對象的方法 MyPlugin.prototype = { init:function(){ //調用私有方法 //處理DOM } } //定義插件myplugin,在插件中使用MyPlugin對象 $.fn.myplugin = function(options){ //創(chuàng)建MyPlugin的實體 myplug = new MyPlugin(this,options); //調用其方法 return myplug.init(); }
從上面的結構可以很清晰地看到,將重要的變量定義到對象的屬性上,在對象中使用變量定義私有方法,在對象的方法中可以調用私有方法從而訪問變量,當需要加入新功能新方法是,只需要向對象添加新的變量和私有方法即可,然后在對象的方法中訪問調用私有方法,再通過插件里實例化的對象調用該方法即可。這樣的好處有:
代碼結構清晰,方便管理、維護
不會影響到外部命名空間,因為變量和方法都是在對象內部
對代碼的改動并不會影響插件的調用,讓$.fn可以專注于插件的調用
自調用匿名函數(閉包)
在代碼量大的情況下,很容易在全局范圍內定義了一些變量,最后很難維護,甚至會跟別人寫的代碼有沖突,所以一般都不會將變量定義全局的,另外一個方法就是始終用自調匿名函數把代碼包裹起來,就可以避免沖突的問題了
自調用匿名函數指(function{....})();
(function{....})();是一個表達式,所以當代碼執(zhí)行到這里的時候,js回去對它求解得到返回值,由于返回值是一個函數,故遇();時,便會被執(zhí)行。然而function{..}();在js預編譯的時候會解釋函數聲明function{...},當代碼執(zhí)行到這里的時候,js會跳過function{..},試圖去執(zhí)行();故而報錯!
函數轉換為表達式的方法并不一定要靠分組操作符(),可以用!操作符,~操作符...
為了防止引入插件報錯,應該在閉包前面加一個分號,即;(function{....})();這樣做為了避免因為其他代碼沒有以分號結尾,引入插件后用來沖到自調匿名函數的第一對括號與別人定義的函數相連,無法正常解析,所以一個好習慣是始終在開頭加上分號";"
下面是一個圖片輪播的例子
;(function($,window,document,undefined){ /*****定義Banner的構造函數******/ //將變量定義到對象的屬性上,函數變成對象的方法,使用時通過對象獲取 var Banner = function(ele,opt){ this.$element = ele, //獲取到的jQuery對象console.log(this); //設置默認參數 this.defaults = { "auto": true, //是否自動播放,默認自動播放 "navActCls": "act", //當前狀態(tài)的class "imgBoxCls": "imgBox", //圖片列表的class "imgNav": "nav", //圖片導航的class "pageBtn": "pageBtn", //prev、next按鈕的class "prevPage": "prev", //prev按鈕的class "nextPage": "next", //next按鈕的class "hideCls": "hide" //隱藏的class }, this.options = $.extend({}, this.defaults, opt); //////定義全局變量 var _ = this, imgWidth = this.$element.width(), //圖片的寬度 $imgBox = this.$element.children("."+this.options.imgBoxCls), //圖片列表 imgBoxWidth = $imgBox.width(), //圖片列表的寬度 $navBox = this.$element.children("."+this.options.imgNav), // 導航 $pageBtn = this.$element.find("."+this.options.pageBtn), // prev、next按鈕 slideTarget = 0, //輪播動畫的目標值 timer = null; //計時器 navIndex = 0; //當前圖片的號數 ///////定義方法 //自動輪播 this.auto = function(){ if(_.options.auto===false){ return false; } clearInterval(timer); timer = setInterval(function(){ _.next(); },4000); } //停止自動輪播 this.stop = function(){ clearInterval(timer); } //下一頁 this.next = function(){ slideTarget -= imgWidth; navIndex = -slideTarget/imgWidth; if(slideTarget<0-imgBoxWidth){ $imgBox.children(":last").remove(); $imgBox.width(imgBoxWidth); $imgBox.css({left:0}); slideTarget = 0-imgWidth; navIndex = -slideTarget/imgWidth; } if(slideTarget===0-imgBoxWidth){ //復制第一張圖片追加到圖片列表末尾,實現(xiàn)無縫輪播 $imgBox.width(function(){ return imgBoxWidth+imgWidth; }); $imgBox.children(":first").clone().appendTo("."+_.options.imgBoxCls); navIndex = 0; } $imgBox.animate({left:slideTarget}); //向左移動值為slideTarget的距離 $navBox.children().removeClass(_.options.navActCls); $navBox.children(":eq("+navIndex+")").addClass(_.options.navActCls); } //上一頁 this.prev = function(){ var $cloneImgBox, // 復制的圖片列表 boolClone; // 是否有克隆的圖片列表 if(slideTarget>0){ $imgBox.css({left:imgWidth-imgBoxWidth}); _.$element.children(":first").remove(); slideTarget = imgWidth - imgBoxWidth; navIndex = $imgBox.children(":last").index(); boolClone = false; } if(slideTarget===0){ //復制圖片列表放到原來的圖片列表前面 $cloneImgBox = $imgBox.clone(); boolClone = true; $cloneImgBox.insertBefore("."+_.options.imgBoxCls); $cloneImgBox.css({left:0-imgBoxWidth}); navIndex = $imgBox.children(":last").index() + 1; } slideTarget += imgWidth; navIndex = -slideTarget/imgWidth; $imgBox.animate({left:slideTarget}); //boolClone=true時在圖片列表向右移動時克隆的圖片列表同時向右移動,實現(xiàn)無縫輪播 if(boolClone){ $cloneImgBox.animate({left:imgWidth-imgBoxWidth}); } $navBox.children().removeClass(_.options.navActCls); $navBox.children(":eq("+navIndex+")").addClass(_.options.navActCls); } //定位圖片 this.position = function(index){ navIndex = index; var actIndex = $("."+_.options.imgNav+" "+"."+_.options.navActCls).index(); if(slideTarget-imgWidth<0-imgBoxWidth){ $imgBox.children(":last").remove(); $imgBox.width(imgBoxWidth); $imgBox.css({left:0}); slideTarget = 0; } if(actIndex===$navBox.children(":last").index() && navIndex===0){ _.next(); } else{ if(navIndex>actIndex){ slideTarget -= imgWidth*(navIndex-actIndex); }else if(navIndex通過這樣的方法來編寫一個插件思路會比較清晰,代碼結構也很清晰容易管理維護
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://m.hztianpu.com/yun/80598.html
摘要:本教程可能不是最精品的,但一定是最細致的。插件開發(fā)下面我們就來看第二種方式的插件開發(fā)。然后我們的插件代碼在這個方法里面展開。 要說jQuery 最成功的地方,我認為是它的可擴展性吸引了眾多開發(fā)者為其開發(fā)插件,從而建立起了一個生態(tài)系統(tǒng)。這好比大公司們爭相做平臺一樣,得平臺者得天下。蘋果,微軟,谷歌等巨頭,都有各自的平臺及生態(tài)圈。 學會使用jQuery并不難,因為它簡單易學,并且相信你接觸...
摘要:這里也提供了幾種不同模式的組件開發(fā)方式,你可以選擇一個適合你的使用輕量級基礎模式為初學者提供的一個簡單通用的基礎模板,包括基礎的默認對象簡單的構造函數默認參數和傳遞參數的合并以及防止對象多次實例化的構造函數的簡單封裝。 在初次進行jquery插件開發(fā)時,我們往往無從下手,當然我們可以按照jquery官方提供的格式進行簡單的插件開發(fā),但是很多時候往往不盡完美,一不小心,就造出一個很...
摘要:就是內部作為全局函數的插件添加到內核上去的。選擇器插件擴充自己喜歡的一些選擇器。在插件里的,經過了一些封裝處理,就是表示對象。調用時,字體大小會運用插件里的默認值 jQuery插件的分類 jQuery插件有很多,有UI類,表單驗證,輸入類,特效類,Ajax類,滑動類,導航類,工具類,動畫類等等。 jQuery的插件主要分為三類: 1、封裝對象方法的插件:也就是基于某個DOM元素的...
摘要:好多編輯器例如等都支持這樣的語法來快速的編寫代碼如何優(yōu)雅地使用把標簽放在結束標簽之后結束標簽之前的差別什么是響應式設計怎樣進行 書籍 《JavaScriptDOM編程藝術》《JavaScript高級程序設計》《JavaScript框架設計》《JavaScript專家編程》《JavaScript Ninjia》《JavaScript語言精粹(修訂版)》《JavaScript設計模式》《J...
摘要:好多編輯器例如等都支持這樣的語法來快速的編寫代碼如何優(yōu)雅地使用把標簽放在結束標簽之后結束標簽之前的差別什么是響應式設計怎樣進行 書籍 《JavaScriptDOM編程藝術》《JavaScript高級程序設計》《JavaScript框架設計》《JavaScript專家編程》《JavaScript Ninjia》《JavaScript語言精粹(修訂版)》《JavaScript設計模式》《J...
閱讀 1966·2021-11-22 15:25
閱讀 1315·2021-11-19 09:40
閱讀 1959·2021-09-27 13:57
閱讀 1067·2021-09-22 15:10
閱讀 1042·2021-08-16 11:01
閱讀 3034·2021-07-23 17:51
閱讀 826·2019-08-30 15:55
閱讀 887·2019-08-30 13:58