轻剑用到顺手处,招式便想自己创。jQuery 的一大好处就在这儿: 你写好的动作,可以收进 $.fn 里,从此变成人人可用的新招式——这就是插件。

本式要点
  • 插件就是挂在 $.fn 上的方法:$('#x').你的方法()
  • 用 $.fn.extend 一次注册多个方法,记得 return this 保住链式
  • 用 $.extend 合并默认选项,让插件可配置
  • 用 $.extend 扩展全局工具函数($.你的工具())
  • 接第三方插件前先问三件事:加载顺序、依赖、能否离线

插件长什么样

jQuery 对象身上的所有方法都存在 $.fn(其实就是 $.prototype 的别名)里。$.fn.addClass、$.fn.fadeIn 都是挂上去的方法——所以你往 $.fn 上再挂一个函数,就造出了新招式:

三步走:给 $.fn 加方法 → 在方法里操作 this → 返回 this。 “返回 this”不是客套,而是让后续方法还能接着点——插件若忘了它, $('#title').hello().addClass(...) 会在中间断掉。

例 1 · 第一个插件:highlight(用 $.fn.extend 注册)

修行语录:日拱一卒、功不唐捐。

注意调用那一行:.highlight().addClass('fw-bold')——插件返回了 this,所以 addClass 还能接上。这就是“保住链式”的实惠。

带选项的插件:默认值 + 用户值

好用的插件都带设置项。标准做法是先立一份默认选项,再用 $.extend 把用户传进来的覆盖上去。这样调用者可以只写关心的一两项, 其余走默认值:

这里多了两件宝贝:其一,var settings = $.extend(默认, options); 其二,return this.each(function () { … })——each 会遍历选中的每一个元素,让插件对一批元素逐个生效。这是 jQuery 插件的经典模板, 背下来也不亏。

例 2 · 可配置的插件:给任务盖章
  • 晨练站桩
  • 临帖一页
  • 读文档半小时

扩展全局工具:$.extend 的另一种用法

给 $.fn 加方法,得到的是“元素身上的招式”; 给 $ 本身加方法(用 $.extend({...})),得到的是 “不依赖元素的小工具”,用法类似上一式的 $.map:

例 3 · 三个自造的小工具
点按钮,看自造工具的结果。

用别人的插件:先问三件事

  • 顺序:插件文件必须排在 jQuery 之后,否则它找不到 $ 可挂;
  • 依赖:有些插件还要 Popper、Moment 之类的伙伴,缺一个就罢工;
  • 离线:把插件文件下载到本地、放进自己的 js 目录——本站不引用任何 CDN, 你的项目也不必。
心法:插件是别人的手,接口是你们的约

用第三方插件前,先读它调用的那几行 API(通常就是 $(选择器).插件名({选项})); 用久了自己写的插件,也要遵守同样的规矩:命名带前缀、选项有默认值、 方法返回 this。前人立约,后人省事——这就是为什么 jQuery 生态里 几十万个插件能彼此相安无事。

练功 · 第十三式
  1. 写一个插件 $.fn.flash():先 fadeOut(200) 再 fadeIn(200), 并保证返回 this。
  2. 给例 2 的 tagIt 插件加一个 size 选项(例如 'sm' / ''), 控制徽章大小(提示:badge 没有尺寸类,可改用 fs-6 之类的字号类)。
  3. 思考题:为什么插件里不能直接用 settings 这个变量名存“每次调用”的设置, 而要先 var settings = $.extend(…)?
参考答案 1

fadeOut 本身返回 this,所以直接用它的返回值即可; 但“显式写一个 return this”是更稳的习惯——将来改动内部实现时, 不会不小心把链式弄断。

参考答案 2

新选项写进默认值对象后,调用者不传就照旧,传了就生效—— 插件的选项表就这样一点点长出来。真实项目里,还会把默认值暴露成 $.fn.tagIt.defaults,方便全局改。

参考答案 3

因为插件方法可能被调用很多次,每次的选项都不同。settings 若是插件外的 “共享变量”,第二次调用就会覆盖第一次的值,先前的元素也会跟着变—— 典型的“一个变量管两家事”。写成 var settings = $.extend(默认, options), 每次调用都得到属于自己的那一份设置,互不干扰。 这也是上一式“深合并时传空对象当目标”的同一个道理:别把别人的默认值改了。

本式小结

  • 插件 = 挂在 $.fn 上的方法,模板是“合并选项 → this.each(操作) → return this”;
  • $.fn.extend 一次注册多个方法,$.extend 扩展全局工具;
  • 默认选项用 $.extend 合并,调用者只用写与默认不同的部分;
  • 接第三方插件先看顺序、依赖与离线,再谈好不好用;
  • 插件的分寸感:做一件事、名字带前缀、永远把 jQuery 对象还回去。
下一式,我们说说“快”——不是招式快,而是让招式少费力气:性能心法。