jQuery UI 实例 – 排序(Sortable)(建议收藏)
💡一则或许对你有用的小广告
欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论
- 新项目:《从零手撸:仿小红书(微服务架构)》 正在持续爆肝中,基于
Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...
,点击查看项目介绍 ;- 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/ ;
截止目前, 星球 内专栏累计输出 82w+ 字,讲解图 3441+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 2900+ 小伙伴加入学习 ,欢迎点击围观
前言:为什么选择 jQuery UI 的 Sortable?
在 Web 开发中,用户界面的交互性是提升体验的核心要素之一。想象这样一个场景:用户需要自由拖拽列表项调整顺序,或是将任务卡片从一个看板移动到另一个看板。这些需求在项目管理、待办事项、内容排序等场景中极为常见。而 jQuery UI 的 Sortable 插件,正是解决这类需求的利器。
Sortable 插件基于 jQuery 构建,通过简单的配置即可实现元素的拖拽排序功能。它不仅支持同列表内的排序,还能让不同列表间互相拖拽,甚至与 Draggable 插件联动。对于编程初学者来说,它提供了直观的 API 和丰富的事件系统,降低了交互开发的门槛。
本文将从零开始,通过循序渐进的案例,带读者掌握 Sortable 的核心功能、高级配置和实际应用。无论你是刚接触前端开发,还是希望优化现有项目的交互逻辑,都能从中获得实用的知识。
一、Sortable 的基础用法:让列表“活”起来
1.1 环境准备与初始化
要使用 Sortable,需先引入 jQuery 和 jQuery UI 的核心文件。通过 CDN 引入的方式快速搭建环境:
<!-- 引入 jQuery -->
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<!-- 引入 jQuery UI 核心及 Sortable 插件 -->
<link rel="stylesheet" href="https://code.jquery.com/ui/1.13.2/themes/base/jquery-ui.css">
<script src="https://code.jquery.com/ui/1.13.2/jquery-ui.min.js"></script>
接下来,准备一个基本的 HTML 结构。例如,一个无序列表:
<ul id="sortable-list">
<li>任务 1</li>
<li>任务 2</li>
<li>任务 3</li>
</ul>
通过一行代码即可初始化 Sortable:
$(document).ready(function() {
$("#sortable-list").sortable();
});
此时,列表项将自动变为可拖拽排序的状态。用户只需点击并拖动列表项的某处,即可调整其位置。
1.2 核心配置选项
Sortable 的强大之处在于其丰富的配置选项。以下是最常用的几个选项:
选项名 | 作用描述 | 默认值 |
---|---|---|
items | 指定可排序的子元素,支持选择器语法(如 > li 表示直接子节点) | >* |
handle | 指定元素内可触发拖拽的区域(如 .drag-handle 类名) | 空字符串 |
placeholder | 设置拖拽时占位符的类名,可自定义样式 | "ui-sortable-helper" |
tolerance | 定义拖拽生效的条件,可选值包括 intersect (元素重叠部分超过 50%)等 | "intersect" |
disabled | 是否禁用排序功能 | false |
示例:限制拖拽区域并添加占位符样式
<!-- HTML 结构 -->
<ul id="sortable-list">
<li><div class="drag-handle">_drag_</div>任务 1</li>
<li><div class="drag-handle">_drag_</div>任务 2</li>
</ul>
<style>
/* 自定义占位符样式 */
.sortable-placeholder {
background-color: #f0f0f0;
opacity: 0.7;
}
</style>
<script>
$("#sortable-list").sortable({
handle: ".drag-handle", // 仅通过 .drag-handle 区域触发拖拽
placeholder: "sortable-placeholder" // 应用自定义占位符类
});
</script>
比喻理解:占位符就像“临时座位”,当用户拖拽元素时,它会标记当前位置的空缺,帮助用户直观感知排序变化。
二、事件系统:捕捉排序过程中的关键节点
Sortable 提供了多个事件钩子,允许开发者在排序的不同阶段执行自定义逻辑。这些事件包括:
- start:拖拽开始时触发
- sort:拖拽过程中持续触发
- stop:拖拽结束时触发
- update:排序完成后触发(仅当 DOM 结构发生改变时)
2.1 实时更新排序结果
一个典型的应用场景是将排序结果实时同步到后端。例如:
$("#sortable-list").sortable({
update: function(event, ui) {
// 获取当前排序后的元素顺序
const newOrder = $(this).sortable("serialize");
// 发送到服务器(此处仅作示例,实际需结合 AJAX)
console.log("排序后的顺序:", newOrder);
}
});
注意:
serialize()
方法会将列表项的id
属性转换为name=value
格式的字符串,例如item[]=1&item[]=3
。若需自定义参数,可通过attribute
选项指定其他属性名。
2.2 动态控制排序行为
通过事件,我们还能实现更复杂的需求。例如,禁止将某些项拖拽到特定位置:
$("#sortable-list").sortable({
beforeStop: function(event, ui) {
// 禁止将“任务 3”放置在第一个位置
if (ui.item.index() === 0 && ui.item.text().trim() === "任务 3") {
alert("任务 3 不能放在首位!");
$(this).sortable("cancel"); // 取消当前操作
}
}
});
三、进阶技巧:与 Draggable 联动与复杂场景实现
3.1 实现跨列表拖拽
Sortable 可与 Draggable 插件结合,实现不同容器间的元素拖拽。例如,将两个列表互相拖拽:
<!-- HTML 结构 -->
<ul id="list-a">
<li>列表 A 项 1</li>
<li>列表 A 项 2</li>
</ul>
<ul id="list-b">
<li>列表 B 项 1</li>
<li>列表 B 项 2</li>
</ul>
// 将两个列表设置为可排序
$("#list-a, #list-b").sortable({
connectWith: ".connectedSortable" // 通过类名连接容器
});
// 为列表添加连接类(确保 connectWith 的选择器匹配)
$("#list-a").addClass("connectedSortable");
$("#list-b").addClass("connectedSortable");
比喻理解:
connectWith
相当于“通行证”,允许元素在指定容器间自由穿梭。
3.2 动态添加/删除项
通过事件结合 DOM 操作,可以实现动态管理列表项:
$("#sortable-list").sortable({
receive: function(event, ui) {
// 当项被拖入时触发
console.log(ui.item.text() + " 被拖入了当前列表");
},
remove: function(event, ui) {
// 当项被拖出时触发
console.log(ui.item.text() + " 被拖出了当前列表");
}
});
四、实战案例:待办事项排序与持久化
4.1 功能需求
- 用户可拖拽调整待办事项顺序
- 排序结果实时保存到本地存储
- 刷新页面后恢复上次排序
4.2 实现步骤
1. 基础 HTML 结构
<div class="todo-container">
<ul id="todo-list">
<li id="todo-1">完成项目需求文档</li>
<li id="todo-2">设计数据库结构</li>
<li id="todo-3">编写单元测试</li>
</ul>
</div>
2. 初始化 Sortable 并绑定事件
$(document).ready(function() {
const $list = $("#todo-list");
// 从本地存储加载排序数据
const savedOrder = JSON.parse(localStorage.getItem("todoOrder")) || [];
if (savedOrder.length) {
$list.html(savedOrder.map(id => $(`#${id}`).clone()));
}
// 初始化 Sortable
$list.sortable({
update: function() {
// 将当前顺序保存到本地存储
const currentOrder = $list.sortable("toArray", { attribute: "id" });
localStorage.setItem("todoOrder", JSON.stringify(currentOrder));
}
});
});
3. 完整代码解析
- 本地存储:使用
localStorage
存储排序后的id
列表,确保页面刷新后顺序不变。 toArray()
方法:返回所有项的id
属性数组,便于序列化存储。clone()
方法:在恢复列表时克隆元素,避免直接移动原始元素导致的 DOM 错乱。
五、性能优化与常见问题
5.1 性能优化建议
- 减少 DOM 操作:在频繁更新场景中,可使用
refresh
方法手动触发重新计算。 - 虚拟滚动:当列表项数量巨大时,结合虚拟滚动技术(如
jquery-ui-sortable-virtual
)提升性能。 - 事件节流:对
sort
事件使用节流函数,防止高频触发导致卡顿。
5.2 常见问题与解决方案
Q:排序后页面布局抖动?
A:检查占位符元素的样式是否与原元素完全一致,包括 width
、height
、margin
等属性。
Q:元素无法拖拽?
A:确认:
- jQuery 和 jQuery UI 是否正确引入
- 元素选择器是否匹配(如
#sortable-list
是否存在) - 是否与其他 CSS 样式冲突(如
pointer-events: none
)
结论:让交互设计更简单
通过本文的讲解,我们已经掌握了 jQuery UI Sortable 的核心用法、事件系统和实战案例。从基础的列表排序到跨容器拖拽,再到与本地存储结合的完整应用,这一插件为开发者提供了灵活且强大的交互解决方案。
对于编程初学者,建议从简单案例开始,逐步添加配置选项和事件逻辑;中级开发者则可以尝试结合动画效果、表单数据绑定等高级功能。记住,掌握工具的最终目标是解决实际问题——无论是优化用户体验,还是提升团队协作效率,Sortable 都是你值得信赖的工具之一。
实践建议:尝试将本文的代码示例部署到本地环境,通过修改配置参数、添加样式或扩展事件逻辑,探索 Sortable 的更多可能性。交互设计的真谛,往往在动手实践的过程中逐渐显现。