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