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