第 6 章 · jQuery 插件开发与性能优化
本章目标:掌握 $.fn.myPlugin 插件模式;了解 validate、datepicker、slick 等常用插件在行业遗留项目中的用法;实践 选择器优化、缓存 $(el)、减少 DOM 查询;简介 jQuery 3.x 与 1.x 差异;为 admin-demo 封装可复用表格增强插件。
学时建议:5~6 小时(含 2 小时跟练)
前置:jquery-layui ch01~ch05。
6.1 插件本质:$.fn 扩展
jQuery 插件通过向 jQuery.fn(即 $.fn)挂载方法,使所有 jQuery 对象可调用。
(function ($) {
'use strict';
$.fn.xzHighlight = function (options) {
var settings = $.extend({
color: '#fdf2f8',
duration: 300
}, options);
return this.each(function () {
var $el = $(this);
$el.css('backgroundColor', settings.color);
setTimeout(function () {
$el.css('backgroundColor', '');
}, settings.duration);
});
};
})(jQuery);
// 使用
$('#product-tbody tr').first().xzHighlight({ color: '#fce7f3' });
| 要点 | 说明 |
|---|---|
| IIFE 包裹 | 避免 $ 冲突,传入 jQuery |
return this.each(...) | 支持链式、遍历多元素 |
$.extend 默认值 | 可选配置 |
return this | each 内可 return this 保持链式 |
6.2 插件模式进阶
6.2.1 方法式插件(字符串分发)
$.fn.xzTable = function (methodOrOptions) {
var args = Array.prototype.slice.call(arguments, 1);
return this.each(function () {
var $table = $(this);
var instance = $table.data('xzTable');
if (!instance) {
instance = new XzTable($table, methodOrOptions);
$table.data('xzTable', instance);
return;
}
if (typeof methodOrOptions === 'string' && instance[methodOrOptions]) {
instance[methodOrOptions].apply(instance, args);
}
});
};
function XzTable($el, options) {
this.$el = $el;
this.settings = $.extend({}, XzTable.defaults, options);
this.init();
}
XzTable.defaults = { pageSize: 20 };
XzTable.prototype.init = function () {
this.$el.addClass('xz-table');
};
XzTable.prototype.reload = function (params) {
// 调用 ch04 Api.getProducts
};
// 调用
$('#product-table').xzTable({ pageSize: 50 });
$('#product-table').xzTable('reload', { page: 2 });
6.2.2 私有方法
(function ($) {
function formatPrice(num) {
return '¥' + parseFloat(num, 10).toFixed(2);
}
$.fn.xzPrice = function () {
return this.each(function () {
var raw = $(this).data('price');
$(this).text(formatPrice(raw));
});
};
})(jQuery);
6.3 常用插件概览
6.3.1 jQuery Validate(表单校验)
<script src="/static/plugins/jquery.validate.min.js"></script>
$('#product-form').validate({
rules: {
name: { required: true, minlength: 2 },
price: { required: true, number: true, min: 0.01 },
stock: { digits: true }
},
messages: {
name: '请输入商品名称',
price: '请输入有效价格'
},
submitHandler: function (form) {
$.post('/api/admin/products/create/', $(form).serialize())
.done(function () { showToast('保存成功'); });
}
});
| 规则 | 说明 |
|---|---|
required | 必填 |
email / url | 格式 |
min / max | 数值范围 |
remote | Ajax 异步校验 SKU 唯一 |
行业常见场景:Layui 表单自带校验(ch08);老 jQuery 页仍可见 Validate。
6.3.2 Datepicker(jQuery UI 或独立版)
$('#date-start, #date-end').datepicker({
dateFormat: 'yy-mm-dd',
changeMonth: true,
changeYear: true,
maxDate: 0
});
订单筛选「开始日期~结束日期」常用。注意与 Layui laydate 不要重复绑定同一输入框。
6.3.3 Slick 轮播
<link rel="stylesheet" href="/static/plugins/slick/slick.css">
<script src="/static/plugins/slick/slick.min.js"></script>
$('#home-banner .banner__slides').slick({
dots: true,
arrows: true,
autoplay: true,
autoplaySpeed: 4000
});
| 插件 | 常见用途 | 依赖 |
|---|---|---|
| Validate | 老表单页 | jQuery |
| Datepicker | 日期筛选 | jQuery UI |
| Slick | 商城首页轮播(可选替代自写) | jQuery |
原则:能用一个库解决的不叠两个;新页优先 Layui / Vue 组件。
6.4 性能优化
6.4.1 选择器优化
// ❌ 慢:通配与深层
$('div.main div.content table tbody tr td');
// ✅ 快:ID + class
$('#product-tbody tr');
// ❌ 重复查询
$('#btn-search').on('click', function () {
$('#product-tbody').empty();
$('#product-tbody').append(row);
});
// ✅ 缓存
var $tbody = $('#product-tbody');
$('#btn-search').on('click', function () {
$tbody.empty().append(row);
});
| 规则 | 说明 |
|---|---|
用 #id | 最快 |
避免 $('*') | 全文档扫描 |
类左侧带标签 $('table.data-table') | 略快于纯 .class |
| 作用域查找 | $panel.find('.js-edit') 而非全局 |
6.4.2 缓存 jQuery 对象
var AdminDemo = {
init: function () {
this.$document = $(document);