JQuery插件機制
js語言靈活性很強,很多的文法是其它語言所不及的,非常的友善。
在JS中{}是對象包,[]是數組包,是以很多位址可以看到{test:1,tes2:2}等内容這個實際就是一個對象包含了兩個屬性。[1,2,3,4]這個實際就是一個數組有四個元素。
開發JQuery插件實際就是給JQuery對象或選擇器對象添加函數,當然可以使用的方法有很多種,如果我們隻給JQuery添加一個函數其實可以用最簡單的方法
jQuery.method_name=function(){
函數主體
}
可以通過jQuery.method_name();來調用這個方法
當然往往在實際中很少出現隻添加一個函數,一般會添加多個函數和多個屬性給JQuery或選擇器對象。那麼用上面的方法就不那麼友善。這個時候就可以使用JQuery内部提供的一個插件機制來批量添加,這樣不但友善,而且可以把一個功能塊包裝在一個插件體内,友善以後修改與更新。
以下是JQuery插件函數代碼(jQuery [email protected]),這段代碼在JQuery的共用性很高如果不了解架構整體不要去修改。
取出JQuery插件機制代碼分析下,進一步了解JQuery插件運作情況,進而更好的去開發插件。當然如有不當之處還請留言指正。
/* JS中可以不寫入傳參,函數内部可以通過arguments來擷取傳入的參數集合通過下标可以取出對應的參數(這算的上是JS的特殊功能吧),函數也運用了條件性遞歸處理。*/
p.extend = p.fn.extend = function() {
/* 初始化局部基本變量,其中 h 取出第一個傳入的參數(如果沒有傳入參數則是undefined),j 擷取傳入參數的個數 */
var a, c, d, e, f, g, h = arguments[0] || {}, i = 1, j = arguments.length, k = !1;
/* 以下代碼是判斷第一個參數不能為布爾值,如果是儲存這個布爾值到k中,再取出第二個參數到h中如果沒有第二個參數寫入空對象。 */
typeof h == "boolean" && (k = h, h = arguments[1] || {}, i = 2),
/* 以下代碼是判斷 h(傳入的第一個參數或第二個參數)是否為對象,不是對象再判斷是否為函數,如果也不是函數就寫入空對象 */
typeof h != "object" && !p.isFunction(h) && (h = {}),
/*以下代碼判斷傳入的參數個數是否與 i(如果第一個參數不是布爾值則為1否則為2)相等,如果相等則h為對象本身(JQuery或選擇器對象)然後i減1 */
j === i && (h = this, --i);
/* 通過上面的初始操作後:
沒有傳入參數: i 為 1,h 為 空對象 ,k 為 false 無意義調用
傳入一個參數:參數為布爾值時 i 為 2,h 為 空對象,k 為 傳入的布爾值 無意義調用;否則 i 為 0 ,h 為 JQuery對象或選擇器對象 , k 為false 插件常用方式傳入的(參數是對象一般以{}形式傳入)
傳入兩個參數:第一個參數為布爾值 i 為 1 ,h 為 JQuery對象或選擇器對象,k 為 傳入的布爾值;否則 i 為 1 ,h 為 傳入的第一個參數(對象或函數)或空對象,k 為 false
傳入兩個以上參數:第一個參數為布爾值 i 為 2 ,h為 傳入的第二個參數(對象或函數)或空對象,k 為 傳入的布爾值;否則 i 為 1 ,h 為傳入的第一個參數(對象或函數)或空對象, k 為false
通過for循環出傳入的參數(如果i不大于j那循環不成立)這個循環體主要是添加擴充,如果沒有進入循環體内的調用都是無意義的調用
循環體内要取到的的變量包含 h , k 。這兩個變量直接受傳入的參數影響。如果第一個參數是布爾值那麼h就是第二個參數
*/
for (; i < j; i++)
/* 判斷是否有傳入對應個數的參數 */
if ((a = arguments[i]) != null)
/* 循環出參數的内容 */
for (c in a) {
/* 取出 h (對象)中對應下标的元素,當然如果沒有那麼 d 為undefined */
d = h[c],
/* 取出循環 a 中對應下标的元素 */
e = a[c];
/* 判斷兩個取出的内容是否絕對性的相同,如果是跳出本次循環處理,進入下次循環進行中 */
if (h === e)
/* 進行下一次循環 */
continue;
/* 如果 k ,e 為真并且 e 是數組或單純對象(非DOM對象)時成立 */
k && e && (p.isPlainObject(e) || (f = p.isArray(e))) ?
/* 以上條件成立時執行:如果e是數組時f為真 */
(f ?
/*如果e是數組那麼置f為false,當d為真并且是數組時g儲存d,否則g為空數組對象。*/
(f = !1, g = d && p.isArray(d) ? d :[]) :
/*如果e不是數組。當d是單純對象(非DOM對象)時g儲存d,否則g為空對象。*/
g = d && p.isPlainObject(d) ? d : {},
/* h在指定的下标進行遞歸處理再擴充功能(但這裡擴充的是h指定下标元素功能。),這次遞歸中k必為真,g為空對象或空數組或為d,e為傳入的第二個及以後的參數(每次隻是一個參數内的屬性或方法)*/
h[c] = p.extend(k, g, e)) :
/* 以上條件不成立時執行:b是架構建立時傳入的第二個參數,一般的架構隻傳入了window是以 b 在這裡隻是undefined,如果你有進階的應用傳入第二個參數來指定b。是以在這裡隻分析e不等于undefined時 把e寫入到h指定下标c中(循環a出來的下标,這裡可以看到給h添加了函數或屬性,如果h是架構對象那麼添加插件功能就實作了) */
e !== b && (h[c] = e)
}
/* 傳回主要是針對遞歸操作 */
return h
根據上面的代碼可以看出擴充JQuery功能:
jQuery.extend(Object)或$.extend(Object) 給架構擴充功能
jQuery.fn.extend(Object)或$.fn.extend(Object) 給選擇器擴充功能
Object一般可以直接以{}形式傳入例如:{test:function(){alert('test')},test1:null}
也可以用其它方法,一般參數是對象或數組。
可以總結一下:擴充功能隻要傳入對象或數組一個參數就可以,當然多個也是可以的。如果先擴充過某個屬性(屬性為單純對象或數組),後還想給這個對象或數組添加一些功能或元素時,就可以在傳入兩個參數(禁止傳入三個參數,否則就是擴充第二個參數的功能而非架構的功能),第一個為布爾值true第二個為要添加的對象或數組,内部下标不要重複,否則會被覆寫。
在插件函數内我們可以使用待擴充的架構所有方法與屬性,可以通過this來調用。
例:添加一個插件,要求能取出指定元素下的所有的圖檔元素并在浏覽器沒有移動到前不顯示圖檔,移動到後才顯示。
代碼如下:
$.fn.extend
({
imgMoverStart:function(imgLoad){ //入囗處,參數為IMG标簽裡儲存圖檔路徑的屬性标簽
this.each(function(){ //循環出元素
if(this.nodeName.toLowerCase()=='img')//判斷循環出來的元素是不是圖檔
$(this).imgShow(imgLoad);//是圖檔加載顯示處理
else //不是再循環子元素
$(this).find('img').each(function(){//取出子元素中的圖檔元素
$(this).imgShow(imgLoad);//加載顯示處理
});
});
},
imgShow:function(imgLoad){//圖檔顯示處理
if(this.get(0).nodeName.toLowerCase()!='img')return;//判斷如果調的元素不是圖檔标簽取消操作
var base=this;//儲存對象本身
$(window).resize(function(){//添加窗囗大小變動事件
$(this).judge(base,imgLoad);//判斷處理顯示
}).scroll(function(){//添加滾動事件
}).judge(base,imgLoad);//初始第一次要必須顯示的圖檔
judge:function(img,imgLoad){//判斷顯示圖檔
setTimeout(function(){//延時處理,減少大量同時請求
var offset=img.offset(),imgimg.attr(imgLoad); //取出圖檔的TOP與圖檔位址資料
base.scrollTop()+base.height()>offset.top&&img.attr('src')!==imgSrc&&img.attr('src',imgSrc);//判斷目前窗囗是否到圖檔的位置,是加載圖檔
},100)//延時0.1秒
}
});
$(window).ready(function(){$('img').imgMoverStart('load_src');})//啟動插件
上面這段代碼主要是處理上下滾動時當窗顯示的内容到了圖檔的上端位置時開始加載圖檔。這個功能很像JQuery的lazyload插件,當然沒有這個插件功能全。
插件是擴充選擇器對象,一共擴充了三個方法,那麼隻要通過 $.('篩選字元').擴充方法名 就可以使用這個插件。在插件内的this就是這個選擇器對象,是以我們可以直接使用this.each() this.get() 等選擇器可以使用的方法基本上都可以拿來用。非常的友善。當然還有很多的擴充方法。但基本相思就是給架構添加功能。
本文轉自 ttlxihuan 51CTO部落格,原文連結:http://blog.51cto.com/php2012web/1285782