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:检查占位符元素的样式是否与原元素完全一致,包括 widthheightmargin 等属性。

Q:元素无法拖拽?
A:确认:

  1. jQuery 和 jQuery UI 是否正确引入
  2. 元素选择器是否匹配(如 #sortable-list 是否存在)
  3. 是否与其他 CSS 样式冲突(如 pointer-events: none

结论:让交互设计更简单

通过本文的讲解,我们已经掌握了 jQuery UI Sortable 的核心用法、事件系统和实战案例。从基础的列表排序到跨容器拖拽,再到与本地存储结合的完整应用,这一插件为开发者提供了灵活且强大的交互解决方案。

对于编程初学者,建议从简单案例开始,逐步添加配置选项和事件逻辑;中级开发者则可以尝试结合动画效果、表单数据绑定等高级功能。记住,掌握工具的最终目标是解决实际问题——无论是优化用户体验,还是提升团队协作效率,Sortable 都是你值得信赖的工具之一。

实践建议:尝试将本文的代码示例部署到本地环境,通过修改配置参数、添加样式或扩展事件逻辑,探索 Sortable 的更多可能性。交互设计的真谛,往往在动手实践的过程中逐渐显现。

最新发布