這是一篇關於jQuery插件開發的文章,下面小編就與大家一起分享。
【前言】
jQuery已經被廣泛使用,憑借其簡潔的API,對DOM強大的操控性,易擴展性越來越受到web開發人員的喜愛,我在社區也發布了很多的jQuery插件,經常有人詢問一些技巧,因此干脆寫這麼一篇文章給各位jQuery愛好者,算是拋磚引玉吧。
【基礎】
a)樣式
很多人會認為樣式是個很復雜的東西,需要沉著冷靜的心態加上非凡的審美觀才能設計出賞心悅目的UI,拋開圖片設計不說,其實css也就是那麼些屬性:position,margin,padding,width,height,left,top,float,border,background...
UI設計的漂亮與否在很大程度上依賴於設計人員對配色的把握和整體效果的協調。舉個簡單的例子,一個簡單的頁面,馬虎的人:
jQuery是一個框架!壓縮後有30多k吧。
細心的人:
body
{
font-family:'宋體';
font-size:12px;
}
jQuery是一個框架!壓縮後有30多k吧。
專心的人:
body
{
font-family:'Verdana','宋體';
font-size:12px;
}
細心的人:
body
{
font-family:'宋體';
font-size:12px;
}
jQuery是一個框架!壓縮後有30多k吧。
專心的人:
body
{
font-family:'Verdana','宋體';
font-size:12px;
}
jQuery是一個框架!壓縮後有30多k吧。
我們對比一下三者的UI效果:
一目了然,或許很多的站點失去關注正是因為這不起眼的font-family,font-size。當然這還只是個簡單的例子,掌握css應該從簡單做起,從基本入手,在實踐中運用並不斷深入。
b)腳本
我們同樣需要對javascript有著深刻的理解,對dom, xhr, Regex, call-apply, prototype等都應該有一定的了解。
有人會說要這些有啥用啊,對dom的操作其實通過getElementById, getElementsByTagName以及其他的API都可以輕松的完成,這話是沒錯,當思路確定後,思想才是重點,一段代碼是精華還是糟粕很容易就可以區分出來,究其原因還是取決你自己,舉個簡單的例子,大量的html組裝,路人甲:
var a = new Array(10);
var menu = '';
for (var i = 0; i < a.length; i++) {
menu += '' + a[i] + '';
}
路人乙:
String.prototype.format = function() {
var args = arguments;
return this.replace(/{(/d{1})}/g, function() {
return args[arguments[1]];
});
};
var a = new Array(1,2,3,4,5,6,7,8,9,0);
var m = '{0}';
for (var i = 0; i < a.length; i++) {
menu += m.format(a[i]);
}
在實現方式明確的情況下,優雅高效的代碼顯然更具吸引力。
【實踐】
jQuery開發或使用,更多的靈感是來自實踐,而不是copy||paste(奉行拿來主義的同學可以離開了)。
那麼在這裡我會用一個簡單的例子來闡述jQuery插件開發的流程,能否舉一反三就看各位看官了。
【目的】
開發一個插件之前我們需要對自己的目的有一個清醒的認識,有很明確的方向感,那麼此次我作為示例插件的目的,就是呈現一個用於UI的Slider - 滑動條,常年從事於或暫時專注於win32開發的同學應該比較了解。
草圖
真正動手編碼之前我們還需要有一個草圖來描述自己插件的“長相”(事件驅動或API封裝的可以忽略)。
很多的同學在做UI開發前往往會忙於搜集各種小圖片(非精通ps或iconworkshop人士),其實漂亮的圖標的確可以美化我們的UI,不過我一般的處理方式是編寫易於擴展的css,前期的UI呈現盡量少使用圖片,多用線條完成。
ok,言歸正卷,那麼我的slider設計草圖是:
解釋下下文將用到的幾個詞:
slider: 此部分是作為拖拽手柄來使用,用戶可以通過拖拽此部分來更新completed bar的位置。
completed: 此部分作為bar的內嵌元素,作為特殊效果來顯示slider與起始點的距離,亦即與slider的value值關聯。
bar: slider的載體,completed的滿值。
思路:
slider作為手柄提供拖拽功能,作用區域為bar,拖拽過程中completed條必須實時更新(長度),影響區域為slider至bar左端的距離。
【編碼】
開發jQuery UI/Effect 插件在很多時候都需要與UI交互,因此在呈現上需要提供Html tree來繪制我們的插件,最終通過js dom來輸出,那麼在繪制簡單的dom結構的時候我會直接用js來完成,不過如果嵌套比較復雜的話,我們還是應該先用html來完成,然後轉變成js輸出。
html tree:
deafultbar -> bar
jquery-completed -> completed
jquery-jslider -> slider
前期UI呈現上我們不使用圖片,盡量用線條、顏色來完成:
Css
將bar的position屬性設置成relative,以方便子節點的浮動(子節點使用position:absolute來獲得內聯浮動效果)。
那麼我們可以看下這個css和html tree產生的UI效果:
ok,具備了所需的元素 - slider, completed, bar.
一些規范:
當我們畫出了UI之後就可以正式編寫jQuery插件代碼了,不過在著之前我們還需要對jQuery插件開發的一些規范性有一些了解。
1. 使用閉包:
(function($) {
// Code goes here
})(jQuery);
這是來自jQuery官方的插件開發規范要求,使用這種編寫方式有什麼好處呢?
a) 避免全局依賴。
b) 避免第三方破壞。
c) 兼容jQuery操作符'$'和'jQuery '
我們知道這段代碼在被解析時會形同如下代碼:
var jq = function($) {
// Code goes here
};
jq(jQuery);
這樣效果就一目了然了。
2. 擴展
jQuery提供了2個供用戶擴展的‘基類’ - $.extend和$.fn.extend.
$.extend 用於擴展自身方法,如$.ajax, $.getJSON等,$.fn.extend則是用於擴展jQuery類,包括方法和對jQuery對象的操作。為了保持jQuery的完整性,我比較趨向於使用$.fn.extend進行插件開發而盡量少使用$.extend.
3. 選擇器
jQuery提供了功能強大,並兼容多種css版本的選擇器,不過發現很多同學在使用選擇器時並未注重效率的問題。
a) 盡量使用Id選擇器,jQuery的選擇器使用的API都是基於getElementById或getElementsByTagName,因此可以知道效率最高的是Id選擇器,因為jQuery會直接調用getElementById去獲取dom,而通過樣式選擇器獲取jQuery對象時往往會使用 getElementsByTagName去獲取然後篩選。
b) 樣式選擇器應該盡量明確指定tagName, 如果開發人員使用樣式選擇器來獲取dom,且這些dom屬於同一類型,例如獲取所有className為jquery的div,那麼我們應該使用的寫法是$('div.jquery')而不是$('.jquery'),這樣寫的好處非常明顯,在獲取dom時jQuery會獲取div然後進行篩選,而不是獲取所有dom再篩選。
c) 避免迭代,很多同學在使用jQuery獲取指定上下文中的dom時喜歡使用迭代方式,如$('.jquery .child'),獲取className為jquery的dom下的所有className為child的節點,其實這樣編寫代碼付出的代價是非常大的,jQuery會不斷的進行深層遍歷來獲取需要的元素,即使確實需要,我們也應該使用諸如$(selector,context), $('selector1>selector2'), $(selector1).children(selector2), $(selctor1).find(selector2)之類的方式。
開始編碼
話題有點扯遠,ok,在對UI有了清晰的認識後我們就可以使用js來輸出html了。
我們使用jSlider來命名這個slider插件(為了避免插件沖突,插件命名時也應十分考究,這裡我就俗一回)。
$.extend($.fn, {
///
/// apply a slider UI
///
jSlider: function(setting) {
}
});
在插件開發中比較標准的方式是將元數據獨立出來並開放API,比如這裡的setting參數傳入值,有時候為了減少代碼編寫量,我習慣於直接在插件內賦值:
var ps = $.extend({
renderTo: $(document.body),
enable: true,
initPosition: 'max',
size: { barWidth: 200, sliderWidth: 5 },
barCssName: 'defaultbar',
completedCssName: 'jquery-completed',
sliderCssName: 'jquery-jslider',
sliderHover: 'jquery-jslider-hover',
onChanging: function() { },
onChanged: function() { }
}, setting);
規范的做法:
$.fn.jSlider.default = {
renderTo: $(document.body),
enable: true,
initPosition: 'max',
size: { barWidth: 200, sliderWidth: 5 },
barCssName: 'defaultba