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自己的方法没有什么区别。

相关文章
相关标签/搜索