當(dāng)我們使用jquery對象的方法時脱惰,由于jQuery對象可以操作一組DOM,而且支持鏈?zhǔn)讲僮髦瘢杂闷饋矸浅7奖恪?br> 但是jQuery內(nèi)置的方法永遠(yuǎn)不可能滿足所有的需求螃概。比如矫夯,我們想要高亮顯示某些DOM元素,用jQuery可以這么實現(xiàn):
$('span.hl').css('backgroundColor', '#fffceb').css('color', '#d85030');
$('p a.hl').css('backgroundColor', '#fffceb').css('color', '#d85030');
總是寫重復(fù)代碼可不好吊洼,萬一以后還要修改字體就更麻煩了训貌,能不能統(tǒng)一起來,寫個highlight()方法冒窍?
$('span.hl').hightlight();
$('p a.hl').hightlight();
答案是肯定的递沪。我們可以擴(kuò)展jQuery來實現(xiàn)自定義方法。將來如果要修改高亮的邏輯综液,只需要需要一處擴(kuò)展代碼款慨。這種方式也稱為編寫jQuery插件。
<p>
</br>
編寫jQuery插件
給jQuery對象綁定一個新方法是通過擴(kuò)展$.fn
對象實現(xiàn)的谬莹。讓我們來編寫第一個擴(kuò)展-------hightlight1():
$.fn.highlight1 = function() {
// this已經(jīng)綁定為當(dāng)前的jQuery對象:
this.css('backgroundColor', '#fffceb').css('color', '#d85030');
return this;
}
注意到函數(shù)內(nèi)部的this
在調(diào)用時被綁定為jQuery對象檩奠,所以函數(shù)內(nèi)部代碼可以正常調(diào)用所有jQuery對象的方法。
對于如下的HTML結(jié)構(gòu):
<!-- HTML結(jié)構(gòu) -->
<div id="test-hightlight1">
<p>什么是<span>jQuery</span></p>
<p><span>jQuery</span>是目前最流行的<span>JavaScript</span>庫附帽。</p>
</div>
來測試一下highlight1()的效果:
$('#test-highlight1 span').highlight1();
執(zhí)行jQuery代碼之后:
細(xì)心的童鞋可能發(fā)現(xiàn)了埠戳,為什么最后要return this;
?因為jQuery對象支持鏈?zhǔn)讲僮鹘栋纾覀冏约簩懙臄U(kuò)展方法也要能繼續(xù)鏈?zhǔn)较氯ィ?/p>
$('pan.hl').highlight1().slideDown();
不然整胃,用于調(diào)查的時候,就不得不把上面的代碼拆成兩行喳钟。
但是這個版本并不完美屁使。有的用戶希望高亮的顏色能自己來指定,怎么辦奔则?
我們可以給方法加個參數(shù)蛮寂,讓用戶自己把參數(shù)用對象傳進(jìn)去。于是我們有了第二個版本的highlight2():
$.fn.highlight2 = function (options) {
// 要考慮到各種情況:
// options為undefined
// options只有部分Key
var bgcolor = options && options.backgroundColor || '#fffceb';
var color = options && options.color || '#d85030';
this.css('backgroundColor', bgcolor).css('color', color);
return this;
}
對于如下HTML結(jié)構(gòu):
<!-- HTML結(jié)構(gòu) -->
<div id="test-highlight2">
<p>什么是<span>jQuery</span> <span>Plugin</span></p>
<p>編寫<span>jQuery</span> <span>Plugin</span>可以用來擴(kuò)展<span>jQuery</span>的功能应狱。</p>
</div>
來實測一下帶參數(shù)的highlight2():
$('#test-highlight2 span').highlight2({
backgroundColor: '#00a8e6',
color: '#ffffff'
});
執(zhí)行highlight2()之后:
對于默認(rèn)值的處理共郭,我們用了一個簡單的&&
和||
短路操作符,總能得到一個有效的值疾呻。
另一種方法是使用jQuery提供的輔助方法$.extend(target, obj1, obj2, ...)
除嘹,它把多個object對象的屬性合并到第一個target對象中,遇到同名屬性岸蜗,總是使用靠后的對象的值尉咕,也就是越往后優(yōu)先級越高:
// 把默認(rèn)值和用戶傳入的options合并到對象{}中并返回:
var opts = $.extend({}, {
backgroundColor: '#00a8e6',
color: 'ffffff'
}, options);
緊接著用戶對highlight2()
提出了意見:每次調(diào)用都需要傳入自定義的設(shè)置,能不能讓我自己設(shè)定一個缺省值璃岳,以后的調(diào)用統(tǒng)一使用無參數(shù)的highlight2()
?
也就是說年缎,我們設(shè)定的默認(rèn)值應(yīng)該能允許用戶修改悔捶。
那默認(rèn)值放哪比較合適?放全局變量肯定不合適单芜,最佳地點是$.fn.highlight2
這個函數(shù)對象本身蜕该。
于是最終版的highlight()終于誕生了:
$.fn.highlight = function (options) {
// 合并默認(rèn)值和用戶設(shè)定值:
var opts = $.extend({}, $.fn.highlight.defaults, options);
this.css('backgroundColor', opts.backgroundColor).css('color', opts.color);
retunr this;
}
// 設(shè)定默認(rèn)值:
$.fn.highlight.defaults = {
color: '#d85030',
bakcgroundColor: '#fff8de'
}
這次用戶終于滿意了。用戶使用時洲鸠,只需一次性設(shè)定默認(rèn)值:
$.fn.highlight.defaults.color = '#fff';
$.fn.highlight.defaults.backgroundColor = '#000';
然后就可以非常簡單地調(diào)用highlight()
了堂淡。
對如下的HTML結(jié)構(gòu):
<!-- HTML結(jié)構(gòu) -->
<div id="test-highlight">
<p>如何編寫<span>jQuery</span> <span>Plugin</span></p>
<p>編寫<span>jQuery</span> <span>Plugin</span>,要設(shè)置<span>默認(rèn)值</span>扒腕,并允許用戶修改<span>默認(rèn)值</span>绢淀,或者運行時傳入<span>其他值</span>。</p>
</div>
實測一下修改默認(rèn)值的效果:
$.fn.highlight.defaults.color = '#659f13';
$.fn.highlight.defaults.backgroundColor = '#f2fae3';
$('#test-highlight p:first-child span').highlight();
$('#test-highlight p:last-child span').highlight({
color: '#dd1144'
});
調(diào)用前:
調(diào)用后:
最終瘾腰,我們得出編寫一個jQuery插件的原則:
- 給
$.fn
綁定函數(shù)皆的,實現(xiàn)插件的代碼邏輯; - 插件函數(shù)最后要
return this;
以支持鏈?zhǔn)秸{(diào)用蹋盆; - 插件函數(shù)要有默認(rèn)值费薄,綁定在
$.fn.<pluginName>.defaults
上; - 用戶在調(diào)用時可傳入設(shè)定值以便覆蓋默認(rèn)值怪嫌。
<p>
</br>
針對特定元素的擴(kuò)展
我們知道jQuery對象有些方法只能作用在特定DOM元素上义锥,比如submit()
方法只能針對form
。如果我們編寫的擴(kuò)展只能針對某些類型的DOM元素岩灭,應(yīng)該怎么寫拌倍?
還記得jQuery的選擇器支持filter()方法來過濾嗎?我們可以借助這個方法來實現(xiàn)針對特定元素的擴(kuò)展噪径。
舉個例子柱恤,現(xiàn)在我們要給所有指向外鏈的超鏈接加上跳轉(zhuǎn)提示,怎么做找爱?
先寫出用戶調(diào)用的代碼:
$('#main a').external();
然后按照上面的方法編寫一個external
擴(kuò)展:
$.fn.external = function () {
// return返回的each()返回結(jié)果梗顺,支持鏈?zhǔn)秸{(diào)用:
return this.filter('a').each(function () {
//注意,each()內(nèi)部的回調(diào)函數(shù)的this綁定為DOM本身车摄!
var a = $(this);
var url = a.attr('href');
if (url && (url.indexOf('http://')===0 || url.indexOf('https://')===0)) {
a.attr('href', '#0')
.removeAttr('target')
.append(' <i class="uk-icon-external-link"></i>')
.click(function () {
if(confirm('你確定要前往' + url + '?')) {
window.open(url);
}
});
}
});
}
對如下的HTML結(jié)構(gòu):
<!-- HTML結(jié)構(gòu) -->
<div id="test-external">
<p>如何學(xué)習(xí)<a >jQuery</a>寺谤?</p>
<p>首先,你要學(xué)習(xí)<a href="/wiki/001434446689867b27157e896e74d51a89c25cc8b43bdb3000">JavaScript</a>吮播,并了解基本的<a >HTML</a>变屁。</p>
</div>
實測外鏈效果:
$('#test-external a').external();
調(diào)用前:
調(diào)用后:
點擊時:
<p>
</br>
小結(jié)
擴(kuò)展jQuery對象的功能十分簡單,但是我們要遵循jQuery的原則意狠,編寫的擴(kuò)展方法能支持鏈?zhǔn)秸{(diào)用粟关、具備默認(rèn)值和過濾特定元素,使得擴(kuò)展方法看上去和jQuery本身的方法沒有什么區(qū)別环戈。