jQuery零基礎入門——(九)擴展

《jQuery零基礎入門》系列博文是在廖雪峯老師的博文基礎上,可能補充了我的的理解和平常遇到的點,用個人理解表述出來,主幹出處來自廖雪峯老師的技術分享。javascript

當咱們使用jQuery對象的方法時,因爲jQuery對象能夠操做一組DOM,並且支持鏈式操做,因此用起來很是方便。css

可是jQuery內置的方法永遠不可能知足全部的需求。好比,咱們想要高亮顯示某些DOM元素,用jQuery能夠這麼實現:html

$('span.hl').css('backgroundColor', '#fffceb').css('color', '#d85030');

$('p a.hl').css('backgroundColor', '#fffceb').css('color', '#d85030');

 老是寫重複代碼可很差,萬一之後還要修改字體就更麻煩了,能不能統一塊兒來,寫個highlight()方法?java

$('span.hl').highlight();

$('p a.hl').highlight();

答案是確定的。咱們能夠擴展jQuery來實現自定義方法。未來若是要修改高亮的邏輯,只需修改一處擴展代碼。這種方式也稱爲編寫jQuery插件。jquery

編寫jQuery插件

給jQuery對象綁定一個新方法是經過擴展$.fn對象實現的,本質是是在原型鏈上開方法,至於原型鏈,有機會的話,咱們會在JS進階裏邊講解。讓咱們來編寫第一個擴展——highlight():app

$.fn.highlight1 = function () {
    // this已綁定爲當前jQuery對象:
    this.css('backgroundColor', '#fffceb').css('color', '#d85030');
    return this;
}

注意到函數內部的this在調用時被綁定爲jQuery對象,因此函數內部代碼能夠正常調用全部jQuery對象的方法。ide

對於以下的HTML結構:函數

<!-- HTML結構 -->
<div id="test-highlight1">
    <p>什麼是<span>jQuery</span></p>
    <p><span>jQuery</span>是目前最流行的<span>JavaScript</span>庫。</p>
</div>

咱們能夠這麼調用:學習

$('#test-highlight1 span').highlight();

細心的童鞋可能發現了,爲何最後要return this?由於jQuery對象支持鏈式操做,咱們本身寫的擴展方法也要能繼續鏈式下去:字體

$('span.hl').highlight1().slideDown();

否則,用戶調用的時候,就不得不把上面的代碼拆成兩行。

可是這個版本並不完美。有的用戶但願高亮的顏色能本身來指定,怎麼辦?

咱們能夠給方法加個參數,讓用戶本身把參數用對象傳進去。因而咱們有了第二個版本的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結構:

<!-- HTML結構 -->
<div id="test-highlight2">
    <p>什麼是<span>jQuery</span> <span>Plugin</span></p>
    <p>編寫<span>jQuery</span> <span>Plugin</span>能夠用來擴展<span>jQuery</span>的功能。</p>
</div>

咱們能夠這麼調用:

$('#test-highlight2 span').highlight2({
    backgroundColor: '#00a8e6',
    color: '#ffffff'
});

對於默認值的處理,咱們用了一個簡單的&&||短路操做符,總能獲得一個有效的值。

另外一種方法是使用jQuery提供的輔助方法$.extend(target, obj1, obj2, ...),它把多個object對象的屬性合併到第一個target對象中,遇到同名屬性,老是使用靠後的對象的值,也就是越日後優先級越高:

// 把默認值和用戶傳入的options合併到對象{}中並返回:
var opts = $.extend({}, {
    backgroundColor: '#00a8e6',
    color: '#ffffff'
}, options);

緊接着用戶對highlight2()提出了意見:每次調用都須要傳入自定義的設置,能不能讓我本身設定一個缺省值,之後的調用統一使用無參數的highlight2()

也就是說,咱們設定的默認值應該能容許用戶修改。

那默認值放哪比較合適?放全局變量確定不合適,最佳地點是$.fn.highlight2這個函數對象自己。

因而最終版的highlight()終於誕生了:

$.fn.highlight = function (options) {
    // 合併默認值和用戶設定值:
    var opts = $.extend({}, $.fn.highlight.defaults, options);
    this.css('backgroundColor', opts.backgroundColor).css('color', opts.color);
    return this;
}

// 設定默認值:
$.fn.highlight.defaults = {
    color: '#d85030',
    backgroundColor: '#fff8de'
}

此次用戶終於滿意了。用戶使用時,只需一次性設定默認值:

$.fn.highlight.defaults.color = '#fff';
$.fn.highlight.defaults.backgroundColor = '#000';

而後就能夠很是簡單地調用highlight()了。

對以下的HTML結構:

<!-- HTML結構 -->
<div id="test-highlight">
    <p>如何編寫<span>jQuery</span> <span>Plugin</span></p>
    <p>編寫<span>jQuery</span> <span>Plugin</span>,要設置<span>默認值</span>,並容許用戶修改<span>默認值</span>,或者運行時傳入<span>其餘值</span>。</p>
</div>

咱們能夠這麼調用:

$.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'
});

最終,咱們得出編寫一個jQuery插件的原則:

  1. $.fn綁定函數,實現插件的代碼邏輯;
  2. 插件函數最後要return this;以支持鏈式調用;
  3. 插件函數要有默認值,綁定在$.fn.<pluginName>.defaults上;
  4. 用戶在調用時可傳入設定值以便覆蓋默認值。

針對特定元素的擴展

咱們知道jQuery對象的有些方法只能做用在特定DOM元素上,好比submit()方法只能針對form。若是咱們編寫的擴展只能針對某些類型的DOM元素,應該怎麼寫?

還記得jQuery的選擇器支持filter()方法來過濾嗎?咱們能夠藉助這個方法來實現針對特定元素的擴展。

舉個例子,如今咱們要給全部指向外鏈的超連接加上跳轉提示,怎麼作?

先寫出用戶調用的代碼:

$('#main a').external();

而後按照上面的方法編寫一個external擴展:

$.fn.external = function () {
    // return返回的each()返回結果,支持鏈式調用:
    return this.filter('a').each(function () {
        // 注意: each()內部的回調函數的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結構:

<!-- HTML結構 -->
<div id="test-external">
    <p>如何學習<a href="http://jquery.com">jQuery</a>?</p>
    <p>首先,你要學習<a href="/wiki/001434446689867b27157e896e74d51a89c25cc8b43bdb3000">JavaScript</a>,並瞭解基本的<a href="https://developer.mozilla.org/en-US/docs/Web/HTML">HTML</a>。</p>
</div>

咱們能夠這樣調用:

$('#test-external a').external();

小結

擴展jQuery對象的功能十分簡單,可是咱們要遵循jQuery的原則,編寫的擴展方法能支持鏈式調用、具有默認值和過濾特定元素,使得擴展方法看上去和jQuery自己的方法沒有什麼區別。

相關文章
相關標籤/搜索