51、JavaScript jQuery扩展

当我们使用jQuery对象的方法时,由于jQuery对象可以操作一组DOM,而且支持链式操作,所以用起来非常方便。

 

但是jQuery内置的方法永远不可能满足所有的需求。比如,我们想要高亮显示某些DOM元素,用jQuery可以这么实现:

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

 

总是写重复代码可不好,万一以后还要修改字体就更麻烦了,能不能统一起来,写个highlight()方法?

  1. $('span.hl').highlight();
  2. $('p a.hl').highlight();

答案是肯定的。我们可以扩展jQuery来实现自定义方法。将来如果要修改高亮的逻辑,只需修改一处扩展代码。这种方式也称为编写jQuery插件。

 

编写jQuery插件

给jQuery对象绑定一个新方法是通过扩展$.fn对象实现的。让我们来编写第一个扩展——highlight1():

  1. $.fn.highlight1 = function () {
  2. // this已绑定为当前jQuery对象:
  3. this.css('backgroundColor', '#fffceb').css('color', '#d85030');
  4. return this;
  5. }

注意到函数内部的this在调用时被绑定为jQuery对象,所以函数内部代码可以正常调用所有jQuery对象的方法。

 

对于如下的HTML结构:

<!-- HTML结构 -->

<div id="test-highlight1">

<p>什么是<span>jQuery</span></p>

<p><span>jQuery</span>是目前最流行的<span>JavaScript</span>库。</p>

</div>

 

来测试一下highlight1()的效果:

  1. 'use strict';
  2. $('#test-highlight1 span').highlight1();

 

什么是jQuery

jQuery是目前最流行的JavaScript库。

 

细心的童鞋可能发现了,为什么最后要return this;?因为jQuery对象支持链式操作,我们自己写的扩展方法也要能继续链式下去:

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

 

不然,用户调用的时候,就不得不把上面的代码拆成两行。

 

但是这个版本并不完美。有的用户希望高亮的颜色能自己来指定,怎么办?

 

我们可以给方法加个参数,让用户自己把参数用对象传进去。于是我们有了第二个版本的highlight2():

  1. $.fn.highlight2 = function (options) {
  2. // 要考虑到各种情况:
  3. // options为undefined
  4. // options只有部分key
  5. var bgcolor = options &amp;&amp; options.backgroundColor || '#fffceb';
  6. var color = options &amp;&amp; options.color || '#d85030';
  7. this.css('backgroundColor', bgcolor).css('color', color);
  8. return this;
  9. }

 

对于如下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>

 

来实测一下带参数的highlight2():

  1. 'use strict';
  2. $('#test-highlight2 span').highlight2({
  3. backgroundColor: '#00a8e6',
  4. color: '#ffffff'
  5. });

 

什么是jQuery Plugin

编写jQuery Plugin可以用来扩展jQuery的功能。

对于默认值的处理,我们用了一个简单的&&和||短路操作符,总能得到一个有效的值。

 

另一种方法是使用jQuery提供的辅助方法$.extend(target, obj1, obj2, ...),它把多个object对象的属性合并到第一个target对象中,遇到同名属性,总是使用靠后的对象的值,也就是越往后优先级越高:

  1. // 把默认值和用户传入的options合并到对象{}中并返回:
  2. var opts = $.extend({}, {
  3. backgroundColor: '#00a8e6',
  4. color: '#ffffff'
  5. }, options);

 

紧接着用户对highlight2()提出了意见:每次调用都需要传入自定义的设置,能不能让我自己设定一个缺省值,以后的调用统一使用无参数的highlight2()?

 

也就是说,我们设定的默认值应该能允许用户修改。

那默认值放哪比较合适?放全局变量肯定不合适,最佳地点是$.fn.highlight2这个函数对象本身。

 

于是最终版的highlight()终于诞生了:

  1. $.fn.highlight = function (options) {
  2. // 合并默认值和用户设定值:
  3. var opts = $.extend({}, $.fn.highlight.defaults, options);
  4. this.css('backgroundColor', opts.backgroundColor).css('color', opts.color);
  5. return this;
  6. }
  7. // 设定默认值:
  8. $.fn.highlight.defaults = {
  9. color: '#d85030',
  10. backgroundColor: '#fff8de'
  11. }

 

这次用户终于满意了。用户使用时,只需一次性设定默认值:

  1. $.fn.highlight.defaults.color = '#fff';
  2. $.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>

 

实测一下修改默认值的效果:

  1. 'use strict';
  2. $.fn.highlight.defaults.color = '#659f13';
  3. $.fn.highlight.defaults.backgroundColor = '#f2fae3';
  4. $('#test-highlight p:first-child span').highlight();
  5. $('#test-highlight p:last-child span').highlight({
  6. color: '#dd1144'
  7. });

 

如何编写jQuery Plugin

编写jQuery Plugin,要设置默认值,并允许用户修改默认值,或者运行时传入其他值。

 

最终,我们得出编写一个jQuery插件的原则:

 

$.fn绑定函数,实现插件的代码逻辑;

插件函数最后要return this;以支持链式调用;

插件函数要有默认值,绑定在$.fn.<pluginName>.defaults上;

用户在调用时可传入设定值以便覆盖默认值。

 

针对特定元素的扩展

我们知道jQuery对象的有些方法只能作用在特定DOM元素上,比如submit()方法只能针对form。如果我们编写的扩展只能针对某些类型的DOM元素,应该怎么写?

 

还记得jQuery的选择器支持filter()方法来过滤吗?我们可以借助这个方法来实现针对特定元素的扩展。

 

举个例子,现在我们要给所有指向外链的超链接加上跳转提示,怎么做?

 

先写出用户调用的代码:

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

 

然后按照上面的方法编写一个external扩展:

  1. $.fn.external = function () {
  2. // return返回的each()返回结果,支持链式调用:
  3. return this.filter('a').each(function () {
  4. // 注意: each()内部的回调函数的this绑定为DOM本身!
  5. var a = $(this);
  6. var url = a.attr('href');
  7. if (url &amp;&amp; (url.indexOf('http://')===0 || url.indexOf('https://')===0)) {
  8. a.attr('href', '#0')
  9. .removeAttr('target')
  10. .append(' &lt;i class="uk-icon-external-link"&gt;&lt;/i&gt;')
  11. .click(function () {
  12. if(confirm('你确定要前往' + url + '?')) {
  13. window.open(url);
  14. }
  15. });
  16. }
  17. });
  18. }

 

对如下的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>

 

实测外链效果:

  1. 'use strict';
  2. $('#test-external a').external();

 

如何学习jQuery?

首先,你要学习JavaScript,并了解基本的HTML。

 

jQuery扩展

小结

扩展jQuery对象的功能十分简单,但是我们要遵循jQuery的原则,编写的扩展方法能支持链式调用、具备默认值和过滤特定元素,使得扩展方法看上去和jQuery本身的方法没有什么区别。

付杰
wp discux 帝国 dedecms phpcms等快速建站
wp discux 帝国 dedecms phpcms等快速建站
  • ¥ 99.9元
  • 市场价:499.9元
PHP运行环境 wamp lamp lnmp 安装 配置 搭建
PHP运行环境 wamp lamp lnmp 安装 配置 搭建
  • ¥ 9.9元
  • 市场价:49.9元
免费SSL证书 HTTPS申请 安装 配置 支持通配符*
免费SSL证书 HTTPS申请 安装 配置 支持通配符*
  • ¥ 199.9元
  • 市场价:20000元
花牛苹果 甘肃天水 李宏恩家自种 1斤 包邮
花牛苹果 甘肃天水 李宏恩家自种 1斤 包邮
  • ¥ 6.8元
  • 市场价:8.8元

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: