jQuery 插件

jQuery 之所以能统治 Web 十年,插件生态是关键推手——鼎盛时期有上万个插件,覆盖轮播、灯箱、表单校验、日期选择、拖拽排序……几乎所有常见交互都有现成插件。本章带你认识插件的本质、学会自己写一个,并了解在 React/Vue 时代怎么看待这套老生态。

1. 插件的本质:$.fn

jQuery 插件的核心机制简单到惊人:$.fn 上挂一个方法$.fnjQuery.prototype 的别名,所有 jQuery 对象共享原型,挂上去的方法所有选区都能调。

// jQuery 插件的本质:往 $.fn 上挂方法
// $.fn 是 jQuery.prototype 的别名,所有 jQuery 对象共享

// 最简单的插件:给所有元素加红框
$.fn.redFrame = function () {
  // this 是当前 jQuery 对象(可能是多个元素)
  this.css("border", "2px solid red");
  return this;     // 关键!返回 this 才能链式调用
};

// 使用
$("p").redFrame().addClass("framed");

// 注意:this 已经是 jQuery 对象,不用再 $(this) 包装
$.fn.logText = function () {
  return this.each(function () {    // 隐式迭代 + 维护链式
    console.log($(this).text());    // each 回调里 this 才是 DOM
  });
};

两个关键点:插件函数里 this 已经是 jQuery 对象(不用 $(this) 包装),必须 return this(或 return this.each(...))才能维持链式调用。这是写插件的第一守则。

2. 经典插件模板

社区沉淀出了一套"标准插件模板":用 IIFE 包装(避免污染全局 + 把 $ 安全地别名化)、用 $.extend 合并默认参数、用 this.each 隐式迭代。背下来就能写出像样的插件。

// 经典插件模板(社区公认最佳实践)
(function ($) {
  $.fn.highlight = function (options) {
    // 1. 默认参数,与传入 options 合并
    const settings = $.extend({
      color: "yellow",
      duration: 1000,
    }, options);

    // 2. 隐式迭代 + 维护链式
    return this.each(function () {
      const $el = $(this);
      const originalBg = $el.css("background-color");

      // 3. 插件逻辑
      $el.css("background-color", settings.color);
      setTimeout(function () {
        $el.css("background-color", originalBg);
      }, settings.duration);
    });
  };
})(jQuery);     // 入参是 jQuery,内部用 $ 别名,避免冲突

// 使用
$("p").highlight();                          // 用默认参数
$("p").highlight({ color: "lightblue", duration: 2000 });  // 自定义
$("p").highlight().addClass("done");         // 链式调用

这个模板有三个亮点:IIFE 包装保证内部 $ 永远是 jQuery,即使外面用了 noConflict$.extend 让插件可配置;return this.each 同时实现了"批量处理"和"链式调用"。

3. 支持方法的进阶插件

复杂插件(如 jQuery UI 的 datepicker)不止能初始化,还能调方法——datepicker("show")。这种插件用方法字典 + 字符串分发实现。

// 进阶:支持方法的插件(像 jQuery UI 的 .datepicker("show"))

(function ($) {
  const methods = {
    init: function (options) {
      return this.each(function () {
        const $el = $(this);
        const settings = $.extend({
          message: "Hello",
        }, options);
        $el.data("plugin", { settings: settings });
        $el.text(settings.message);
      });
    },
    show: function () {
      return this.each(function () {
        $(this).show();
      });
    },
    hide: function () {
      return this.each(function () {
        $(this).hide();
      });
    },
    destroy: function () {
      return this.each(function () {
        $(this).removeData("plugin").off(".myPlugin");
      });
    },
  };

  $.fn.greeter = function (methodOrOptions) {
    if (methods[methodOrOptions]) {
      return methods[methodOrOptions].apply(this, Array.prototype.slice.call(arguments, 1));
    } else if (typeof methodOrOptions === "object" || !methodOrOptions) {
      return methods.init.apply(this, arguments);
    } else {
      $.error("方法 " + methodOrOptions + " 在 greeter 上不存在");
    }
  };
})(jQuery);

// 使用
$("#box").greeter({ message: "你好" });    // 初始化
$("#box").greeter("hide");                  // 调用方法
$("#box").greeter("destroy");               // 销毁

这种模式让你写出 greeter 初始化、greeter("destroy") 销毁的 API——和官方插件风格一致。提供 destroy 方法是好插件的标准,让使用者能干净地释放资源。

4. 著名的 jQuery 插件生态

十年间涌现了无数经典插件,下面这些你大概率见过甚至用过:

// 著名的 jQuery 插件生态(鼎盛时期)

// 1. jQuery UI - 官方扩展,提供拖拽/排序/日期选择/对话框等
<script src="https://code.jquery.com/ui/1.13.2/jquery-ui.min.js"></script>
$("#dlg").dialog();              // 一行弹出对话框
$("#list").sortable();           // 列表可拖拽排序
$("#date").datepicker();         // 日期选择器
$("#tabs").tabs();               // Tab 选项卡

// 2. Slick - 最流行的轮播图插件
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/slick-carousel@1.8.1/slick/slick.min.css" />
<script src="https://cdn.jsdelivr.net/npm/slick-carousel@1.8.1/slick/slick.min.js"></script>
$(".slider").slick({
  autoplay: true,
  dots: true,
  arrows: true,
});

// 3. Lightbox / Fancybox - 图片灯箱
<a class="lightbox" href="big.jpg"><img src="thumb.jpg" /></a>
$(".lightbox").lightbox();

// 4. Select2 / Chosen - 美化下拉框
$("select").select2();

// 5. jQuery Validate - 表单校验(至今最常用)
$("form").validate({
  rules: { email: { required: true, email: true } },
  messages: { email: { required: "请填邮箱" } },
});

即使在新项目里,jQuery Validate(表单校验)和 Select2(美化下拉框)仍是不少团队的默认选择——它们专注、稳定、文档完善,比很多"现代替代品"更省心。维护老代码时,认得这些名字就能快速定位。

5. 现代项目里怎么对待 jQuery 插件

新项目还要不要用 jQuery 插件?答案是看场景

// 现代项目里 jQuery 插件怎么处理?

// 1. 老项目维护:照常用
//    WordPress / 老企业系统 仍依赖 jQuery 插件
//    Bootstrap 4 及以前 用 jQuery + Popper.js

// 2. 新项目替代方案
`jQuery UI 拖拽`      →  SortableJS / react-dnd / @dnd-kit
`jQuery Validate`     →  zod / yup / ajv / HTML5 原生校验
`Slick 轮播`         →  Swiper / embla-carousel
`Lightbox`           →  photoswipe / glightbox
`Select2`            →  Choices.js / Tom Select
`DatePicker`         →  flatpickr / pikaday

// 3. 给现代框架写"插件"的思路
// React: 自定义 Hook + 组件,而非扩展 React 对象
// Vue:   app.use(plugin) / 组合式函数
// 这些都基于"组件 + 数据驱动",而非 jQuery 的"扩展原型"

// 4. 哪些场景 jQuery 插件仍是合理选择?
//  - 老项目维护(改造成本太高)
//  - 简单营销页/官网(引个 jQuery 比配 React 构建快)
//  - 嵌入第三方系统(CMS / LMS / 邮件模板编辑器)
//  - 内部工具脚本(一次性、不需长期维护)

核心判断标准:项目生命周期 + 团队技术栈 + 维护成本。短期营销页、老项目维护、嵌入 CMS——jQuery 插件仍是合理选择;长期维护的产品代码、技术栈已用 React/Vue——优先找现代替代品。别为了"现代化"而强行重写老代码,成本收益常常不划算。

6. 写插件的几条忠告

如果真的要写 jQuery 插件(维护老项目或简单页面),记住这几条经验:

系列总结

恭喜你走到了 jQuery 系列的最后一篇。回顾一下学过的:

jQuery 是一座历史桥梁——理解它,你就理解了过去十年 Web 是怎么走过来的;会读它,你就能维护互联网上过半的存量代码。下一步可以去看看 Bootstrap 教程——它和 jQuery 是同代搭档,至今仍是快速建站利器。

← 上一篇 jQuery 链式调用

← 返回 jQuery 教程目录

✈️💬